Floating Banner

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 JavaScript (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="right-pointing-hand.png" alt style="margin-right:20px">
Fabulous Floating Banner
		<img src="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) HTML to save space.

To this I’ll add some CSS:

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

Then the JQuery. 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');
	}
   })
});

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.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.