demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Floating Banner

“Scroll To Top Then Fixed” Effect With JQuery

javascript / scroll effects

Estimated reading time: 3 minutes, 30 seconds

Of late there has been a UI trend of page elements (usually navigation items) that scroll with the rest of the page until they reach the top of the browser window. At this point those elements stop moving, while the rest of the page’s content continues to scroll up behind them. This trick – referred to variously as “scroll to top then fixed” or “fixed floating elements” can’t be achieved with alone, at least at this stage; we must integrate some (for this example, in the form of JQuery) to pull the effect off.

First, let’s create an element to apply the technique to. In my case, it will be a banner, in the form of an article’s header element:

<article>
<header id=fixadent>
<img src=/assets/images/right-pointing-hand.png alt="" style=margin-right:20px>
Fabulous Floating Banner
<img src=/assets/images/left-pointing-hand.png alt="" style=float:right>
</header>
<p>… lots and lots of content…
</article>

A couple of points to note; the element I want to apply this effect to could be absolutely anything; in this case, it happens to be a header element. I’m also using absolutely minimal (but still valid) to save space.

To this I’ll add some :

header { text-transform: uppercase; font-size: 38px; padding: 20px 0; }
header img { width:106px; height: 41px; vertical-align: middle; float: left; }

Then the code. We’ll use an alternative shortcut to $(document).ready() to get us started:

$(function() {
   var fixadent = $("#fixadent"), pos = fixadent.offset();
   $(window).scroll(function() { 
     if($(this).scrollTop() > pos.top && $(fixadent.css('position') == 'static'))
	{ $(fixadent).css('position',’fixed’); } 
})
});
});

The code is pretty simple: we create a variable, fixadent, to act as the reference to our banner with a matching id, and pos, which constantly monitors the position of the element.

When the window scrolls, we check if the scrolled position of the window is greater than the top position of the fixadent element. (Imagine that scrollTop starts at 0, when the vertical scrollbar is at the top of the browser window. scrollTop is incremented by the number of pixels the scrollbar is moved down.) If scrollTop becomes greater than the position of the header element (which is measured from the top of the page, not the browser window), and the element has position: static (i.e. the default), we set it to position: fixed.

This code is somewhat limited: you may find that the header elements “fires off” a little early, and jumps somewhat. Adding position: fixed via JavaScript still inherits the other CSS we have applied. We’ll adjust the existing style for the header:

header {
background: linear-gradient(to bottom, rgba(241,241,228,1), rgba(241,241,228,0));
}

And fire the “fixed” state a little sooner by adding to pos.top:

if($(this).scrollTop() > (pos.top + 10) && $(fixadent.css('position') == 'static'))
{ $(fixadent).addClass('fixed'); }

…and create a class to specify more changes to our element in its fixed position. Anything more than a single change to CSS should usually be written as a class, rather than being applied directly via JavaScript:

.fixed { position: fixed; top: -20px; }

Now you should be able to see why we added the linear gradient: without it, the header element rather viciously cuts off any text that slides underneath it; the gradient makes the content appear to fade out as it slides up.

Finally, we need to free up the header element and return it to its original location if the user scrolls back to the top of the page:

$(function() {
   var fixadent = $("#fixadent"), pos = fixadent.offset();
   $(window).scroll(function() { 
     if($(this).scrollTop() > (pos.top + 10) && fixadent.css('position') == 'static') { fixadent.addClass('fixed'); } 
     else if($(this).scrollTop() <= pos.top && fixadent.hasClass('fixed')){ fixadent.removeClass('fixed'); }
   })
});

That’s it! (You may also notice that I’ve also added a third state for the element in the example for this article: if you scroll down more than 500 pixels, the banner disappears… I didn’t want it to become too annoying.

You can take this idea a lot further, and several sites have. Examples include the promotional site for the Nizo app, nizo, newzealand.com and Ben The Bodyguard

As always, make sure that you’re imparting useful features and information, not just gimmicks. Tricks on web pages quickly become passé, but good content is eternal.

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.