I would like to create an interface with 3 columns, each having mixed content (text, image, and video), and would like to have them scroll vertically with different speeds at the same time. Is there a relatively simple way of accomplishing this with html, css, and/or javascript?
PS. I know about the parallax scrolling, but the implementations I came across seem to be mostly about using images as background to create a dimensional illusion.
Something like: http://jsfiddle.net/KVWuS/.
$.fn.makeScroll = function(speed) {
var elem = this,
i = 0;
setInterval(function() {
elem.scrollTop(i++); // increment scroll top
}, speed); // run every 'speed' ms (so lower is faster)
};
You can enable it like:
$('div:eq(0)').makeScroll(75); // moderate speed
You want to actually scroll the content?
$('.column').animate({
scrollTop: $('.column').height() - $(window).height()
}, 1000);
This will scroll your column down in 1 second. Adjust the speed per column.
EDIT:
I was assuming your columns were the height of the window. If not, you'll have to adjust the scrollTop.
I think a simple workaround would be to create 3 div Elements with the following Attributes:
overflow: hidden;
width: x px (fixed width)
height: x px (fixed height)
top: 0px;
left: x px;
Then you have to capture the onscroll event and set the top-Attribute.
E.g.
div1: top: -100px
div2: top: -300px
div3: top: -500px
I hope my description is clear.. :)
That should work
Related
What would be the best way to achieve the following:
I would like to get a big centered logo, to shrink and move to the top left of the page as you scroll down and become part of the nav bar.
I would also like a nav bar to fade down from the top.(I only know how to do this timed not dependent on scroll)
When the site loads it will look like just a logo with a simple background. When you scroll down the logo will shift to the top left and the nav bar will ease in and the background picture will also move up out of sight.
Is there any way that you can do the transformation dependent on how far you have scrolled. So that if you stop half way your transformation will also stop?
If I understand you correctly, you want to make a transition to the nav bar / header and the logo dependent on how much you have scrolled, while you are scrolling? If so, it is not as hard is it might sound.
First we have to find out, how many pixels you have scrolled on the page and how many pixels to scroll before the transition is complete. Se code example below.
$(window).on("scroll", function() {
var yPos = $(this).scrollTop(),
yPer = (yPos / 120);
if (yPer > 1) {
yPer = 1;
}
});
Here the y position of the page is found yPos and the transition is set to complete when scrolled down 120 pixels. With these informations we can then calculate the percentage of scrolled pixels until reaching 120 pixels; yPer.
0px = 0%, 60px = 50%, 120px = 100%
In the if-statement we make sure, that the percentage cannot exceed 100%.
HTML and CSS part
Before we go any further with the JavaScript part, let’s setup the HTML and CSS.
HTML structure:
<header></header>
<img class="logo" src="http://oi68.tinypic.com/2z5m4pu.jpg" />
In this case the logo is not inside the header, since we are going to hide the header by default, which would also hide all the child-elements including the logo, which we do not want.
Hiding the header/nav bar:
header {
width: 100%;
height: 60px;
background: #FFF;
position: fixed;
top: -60px;
opacity: 0;
}
Since you want the header to fade in from the top while scrolling, top is set to the negative height of the header itself and the opacity to 0.
Centering the logo:
img.logo {
height: 200px;
position: fixed;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
}
In this way we are going to center the logo in the middle of the screen, no matter the size and resolution of the browser window. If the values in top, left and translate3d all where set to 0, the logo would be in the top left corner. That's why this is a good way to do it in our situration.
JavaScript part - continued
Now we're ready the continue with the JavaScript part.
Store heights in variables:
var header = $("header"),
headerHeight = header.height(),
logo = $(".logo"),
logoHeight = logo.height();
$(window).on("scroll", function() {
// Rest of our code
});
To make it a lot easier for us self later on, we are going to automatically find the height of both the header and the logo, and store those in variables. By doing this we don’t have to change anything in the JavaScript code, if we later on in the future wants to change the height of our elements. We only have to change it, in the CSS.
We are going to set those variables before our scroll-function since, they do not change while scrolling as seen above.
The Calculations:
var logoPos = ( -1*(yPer * 50) + 50),
logoSize = ((headerHeight * yPer) - (logoHeight * yPer) + logoHeight),
headerPos = ((yPer * headerHeight) - headerHeight);
This is a very important part of our code. These expressions are the once that calculates how the elements should animate as we scroll.
logoPos: Calculating the new position of the logo as we scroll. We know that the top, left and translate3d always has
a value of "50". | Starts on 50, ends on 0.
logoSize: Calculating the size of the logo as we scroll. | Starts on the height of the logo, ends on the height of the
header.
headerPos: Calculating the position of the header as we scroll. | Starts on the negative height of header, ends on 0.
NOTE: If we didn’t stored the heights of your elements like before, we had to manually change them in calculations if we later wanted to change them.
Add the new styles:
logo.css({
top: logoPos + "%",
left: logoPos + "%",
transform: "translate3d(-" + logoPos + "%,-" + logoPos + "%,0)",
height: logoSize
});
header.css({
top: headerPos,
opacity: yPer
});
Here we using all our calculations to style our elements as we scroll. On the logo at translate3d we have to remember to put a minus before the logoPos. Else the logo will start moving from the bottom right instead of the center.
For the opacity, we don't have to calculate anything. We just use the yPer.
Well that’s basically it. Hope this could help you out.
You can se the full code in context and with comments in this fiddle:
Working Fiddle
If I understand your question correctly then you should use $(window).scrollTop().
For example in your javascript file,
$(document).ready(
function () {
setInterval(function () {
if ($(window).scrollTop() >= 650) {
// Move your logo to where you want
}
else{
//Move the logo back to the original position
}
}, 1000);
});
This code will check if the current top of your scroll is past 650px and will trigger that code. If it's less than 650px they it will trigger the other code to move your picture back. The setInterval is used so it will constantly check every 1 second but you can change that to suit your needs.
Change the 650 to whatever you think fits best.
It kind of hard to figure out your problem without providing any code but I hope this helps.
I'm trying to understand how to animate more elemets at the same time in jQuery.
Let's say I have a simplified code like this:
var $targetElement = $('#target-element');
var offset = $targetElement.offset();
var width = $targetElement.outerWidth();
var height = $targetElement.outerHeight();
var bodyWidth = $('body').width();
var bodyHeight = $('body').height();
$topHelper.animate({
height: offset.top
});
$rightHelper.animate({
top: offset.top,
width: bodyWidth - offset.left - width,
height: height
});
$bottomHelper.animate({
height: bodyHeight - offset.top - height
});
$leftHelper.animate({
top: offset.top,
width: offset.left,
height: height
});
Where the targetElement is an element somwhere in the body and all those helpers are black semitransparent absolutely positioned layers (right on the body) which should get to sorround the targetElement's bounding box.
The problem is that during the animation I can see tiny (1px - 3px) gaps or overlaps between the animated layers. It's on the edges where the layers shoud be always next to each other. I think it's because I animate 4 elements and every element has its own 'fx' queue. So there are 4 timers and the 'frame refresh' is not at the same time for all of them.
Is it true or am I totally wrong? How can I synchronize animation of more elements?
EDIT From comments below:
Well, I don't understand how to use css animations here. I think they are declarative and I need to animate to a dynamically computed positions.
requestAnimationFrame looks promising, unfortunatelly I need to support IE9.
I would really appreciate an answer regarding to the jQuery animations. More specifically, are my assumptions about 4 timers right? If yes, is it possible to animate more elements in one 'queue' - that is recompute all 4 element positions in every 'frame repaint' together?
I'm trying to create a website with main content area and a sidebar, something like here on Stack Overflow. The goal is that when you scroll down, the sidebar stays visible.
I have seen two approaches to this:
position:fixed;
JavaScript manipulation with the DOM
Approach no. 1, as far as I know, will have a problem when the viewport is smaller than the sidebar contents so I guess that can't be used reliably and JavaScript scripts that I have seen are usually animated or generally "slow" (you can see that there is redrawing going on after each scroll).
Can someone point out a JavScript library / CSS approach that would not suffer from the aforementioned issues?
Edit: an example would be this page but with the sidebar sticking to the top without an animation and correctly handling the situation when the sidebar is higher than content / viewport.
I don't like heavy JS solutions, so important thing to ask is - preferred compatibility. In IE8+ it is possible instead of
var $window = $(window),
$sidebar = $(sidebar);
$window.on('resize', function(){
$sidebar.height($window.innerHeight());
});
$window.resize();
do something like this (pure CSS solution):
#sidebar {
position: fixed;
left: 0; /* or right */
top: 0;
bottom: 0;
overflow: auto;
}
When you have top&bottom / left&right value at the same time, box will be stretched. (JSFiddle demo)
Got it. It is Javascript based, but I'm sure that's nothing heavy and even IE8 should solve it pretty fine.
var top = $('#sidebar').offset().top;
var height = $('#sidebar').height();
var winHeight = $(window).height();
var gap = 10;
$(window).scroll(function(event) {
var scrollTop = $(this).scrollTop();
// sidebar reached the (end - viewport height)
if (scrollTop + winHeight >= top + height + gap) {
// if so, fix the sidebar and make sure that offset().top will not give us results which would cancel the fixation
$('#sidebar').addClass('fixed').css('top', winHeight - height - gap + 'px');
} else {
// otherwise remove it
$('#sidebar').removeClass('fixed').css('top', '0px');
}
});
demo
You could catch client window's height and giving it to your sidebar like this :
var sidebarHeight = $(window).innerHeight();
$('#sidebar').css('height',sidebarHeight);
With the proper CSS for the sidebar :
#sidebar {
position: fixed;
right: 0;
top: 0;
width: 200px;
overflow: hidden;
}
Here is a working JSFiddle.
You could also watch for window resizing to avoid a mess on resize :) Here is the way to go with jQuery
Good luck
Not sure if you have this figured out but I have created a contained sticky sidebar jQuery plugin. It's really simple and allows you to invoke with just one line of jQuery. Take a look here: http://mojotech.github.com/stickymojo/
It starts by position: fixed; then uses javascript to handle any resizes, scrolls and even allows you to specify a footer element that it should not intersect. By combining these approaches you will get a smooth looking fixed element. Plus, we made it easy for you.
Code and demo here: http://closure-library.googlecode.com/svn/docs/class_goog_ui_ScrollFloater.html
I'm building a site with a fluid layout, and therefore need to use percentages in my Jquery sizes and animations. The problem, as I've discovered, is that Jquery doesn't understand percentages. Here's an example of what I'm after:
The page <body> is 100% wide.
<article> is the width of 71% of the page body.
<hgroup> is the width of 33.2% of <article>
I would like <article> to be the same width as <hgroup> on page load (so that only <hgroup> is showing), then expand to 71% of the page width again when <hgroup> is clicked, allowing the rest of the content within <article> to show. At the same time, I'd like <article> to slide left by the width of <hgroup>, hiding <hgroup>.
Is there any way to make this kind of calculation, or will I have to resort to pixels?
Well, you can define
article {
width: 23.6%;
/* that's 33.2% of 71% of 100 */
}
hgroup {
width: 100%;
/* that's in relation to article */
}
plus whatever positioning you need
then
$('article').width($('body').width() / 100 * 71);
$('hgroup').width($('article').width() / 100 * 33.2);
plus whatever effects you need
After much frustration and lamentation, I finally got it sorted out. Here's the code I came up with which, miraculously, works:
$(document).ready(function() {
$('section').hide();
//Capture widths on page load
var bwidth = $('body').width();
var awidth = $('article').width();
var hgwidth = $('hgroup').width();
$('hgroup').width(hgwidth);
$('article').width(hgwidth);
$('hgroup').click(function(){
//Hide open article
var close = $('section:visible').parent();
$(close).children('section').hide().end().width(hgwidth);
$(close).removeClass('active').css('marginLeft', '+=' +hgwidth).detach().appendTo('body');
//Hide last Article
$('body article').last().hide();
//Show current
$(this).parent().addClass('active')
$('.active').animate({
width: awidth,
marginLeft: '-=' + hgwidth
},500);
$(this).next().delay(500).fadeIn(50);
$(this).css('box-shadow','0px 0px 8px #666');
//Show Next Hgroup
$(this).parent().nextAll('article:first').show();
});
});
I think you are looking for slide effect. Take a look at jquery ui slide effect http://docs.jquery.com/UI/Effects/Slide. It might help you without much coding.
i am initially centering div horizontally using jquery but when the window is resized it looks bad so what i want to do is keep it centered using jquery after the window is resized
is there a way to help?
EDIT
guys i have successfully made other elements centered but i am having another issue now :(
please check this
http://hrmanagementbradford.com/gallery/
and resize the window, you will see that the content doesn't get positioned correctly, i am trying to fix this for hours but can't find the solution please help with that
EDIT
solved! it was complex and my code is very specific so posting it here won't help :)
and
although i used jquery to center it but if we use the css thing then FutureKode's answer is best suited for me :)
Why are you using jquery to center horizontally when css can do it one line and it will stay in the center when the browser is resized:
div {
margin:0 auto;
width:800px
}
You can make it dead-centered like this:
$('#elementID').css({
position:'absolute',
top:'50%',
left:'50%',
width:'600px', // adjust width
height:'300px', // adjust height
zIndex:1000,
marginTop:'-150px' // half of height
marginLeft:'-300px' // half of width
});
Note that element will appear at the center but with scrolling it won't move. If you want to make it appear at center, you need to set position to fixed instead. However, this won't work in IE6. So decision is yours :)
You can also create quick simple jQuery plugin:
(function($){
$.fn.centerIt = function(settings){
var opts = $.extend({}, $.fn.centerIt.defaults, settings);
return this.each(function(settings){
var options = $.extend({}, opts, $(this).data());
var $this = $(this);
$this.css({
position:options.position,
top:'50%',
left:'50%',
width:options.width, // adjust width
height:options.height, // adjust height
zIndex:1000,
marginTop:parseInt((options.height / 2), 10) + 'px' // half of height
marginLeft:parseInt((options.width / 2), 10) + 'px' // half of height
});
});
}
// plugin defaults - added as a property on our plugin function
$.fn.centerIt.defaults = {
width: '600px',
height: '600px',
position:'absolute'
}
})(jQuery);
And later use it like:
$('#elementId').centerIt({width:'400px', height:'200px'});
To center it when window is resized, you would use resize event just in case it does not center like this:
$(window).resize(function(){
$('#elementId').centerIt({width:'400px', height:'200px'});
});
You can use
margin: 0 auto;
to centre a block element horizontally in CSS.
Like so:
div
{
width: 400px;
margin: 0 auto;
}
do this:
$(window).resize(function(){
// reposition div again here
})