Sticky CSS - JS function

10th January 2014

Sticky position css is where an element remains attached to the browser viewport when the user scrolls until it exceeds the size of it's parent. It has become popular in web design recently and has even made its way into the standards.

Live Demo

Just scroll down past the first below. It will stick with the scrolling until it reaches the bottom of its container and remain there.

Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque ullamcorper iaculis tempus. Sed justo odio, tempor at turpis ut, volutpat vulputate ipsum. Integer eget semper eros. Pellentesque luctus orci lobortis elit commodo, eu cursus dui tincidunt.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vulputate convallis magna, tempus feugiat leo tempus et. Nullam at eleifend est. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed sem mi, rutrum vitae venenatis id, rutrum ac risus. Etiam scelerisque nisl et ipsum sollicitudin, sed vehicula quam posuere. Fusce ut tortor quam. Proin et tortor sed magna ornare sodales nec quis nulla. Etiam risus metus, egestas et suscipit consectetur, iaculis sit amet eros. Sed sit amet blandit elit. Curabitur tempor lectus euismod libero rutrum eleifend. Morbi id velit eros. Sed purus ipsum, fermentum ultricies augue tempus, tristique scelerisque arcu. Suspendisse et nisl vitae nisi vehicula fringilla. Duis vel porta lectus.

Nunc tortor tellus, tempus sit amet sem quis, ultricies placerat nunc. Nunc vitae consequat purus, in ornare quam. Integer est lorem, aliquam ac sollicitudin volutpat, facilisis eu elit. Curabitur rhoncus, enim eu suscipit luctus, ipsum purus ornare erat, eget pharetra tellus mauris sit amet nisi. In risus arcu, laoreet non tortor molestie, venenatis eleifend dolor. Proin at sem justo. Aenean tristique bibendum sapien, in sodales est blandit ut. Vestibulum massa tellus, pretium in dapibus nec, consequat ut nunc. Maecenas ut elit bibendum ligula ultrices fermentum. Quisque accumsan lorem a vestibulum hendrerit. Etiam eget elit aliquet, elementum diam vel, pharetra dolor.

CSS

The following CSS is required to make the sticky behavour work correctly:

.sticky_decoy.invisible {
display: none !important;
}

.sticky {
position: fixed;
top: 0px;
}

.sticky_bottom {
position: absolute;
bottom: 0px;
top: auto;
}

Javascript

Note: requires jQuery to function correctly.

function makeSticky($dom) {
	$dom.each(function() {
		var $dom = $(this);
		
		//make a record of the original offset of the element
		var origOffset = $dom.offset();
		var origOuterHeight = $dom.outerHeight();
		var origPos = $dom.position();
		
		var origHeight = $dom.height();
		var origWidth = $dom.width();
		
		var $parent = $dom.parent();
		
		//the dom sticks to the sides of the screen during scrolling if the viewport is scrolled beyond the visibility of the dom
		//its maximum scroll amount is contained in its parent or another provided dom element so that it sticks to its parent element
		//we use a empty object decoy to replace the original dom element and then layer the original on top so other inline elements are not affected by the change of dom layout
		//so this can be called very simply on a dom element
		var $decoy = $('<div class="sticky_decoy invisible"></div>');
		$decoy.css({ 
			width: $dom.outerWidth(true), 
			height: $dom.outerHeight(true), 
			top: $dom.position().top, 
			left: $dom.position().left,
			display: $dom.css("display"),
			position: $dom.css("position"),
			float: $dom.css("float"),
			clear: $dom.css("clear")
		});
		
		$dom.before($decoy);
		
		$(window).on("scroll resize", handleScroll);
		handleScroll();
		
		function handleScroll() {
			var scrollPos = {top: $(window).scrollTop(), left: $(window).scrollLeft() };
			
			var slideDown = scrollPos.top > origOffset.top, stayDown = scrollPos.top + origOuterHeight > $parent.offset().top + $parent.height();
			
			if (slideDown && !stayDown) {
				if (!$dom.hasClass("sticky")) {
					$decoy.removeClass("invisible");
					$dom.addClass("sticky");
					
					window.setTimeout(function() {
						$dom.css({width: origWidth, height: origHeight, left: $decoy.offset().left});
					}, 0);
				}
			} else {
				$dom.attr("style" ,"").removeClass("sticky");
				$decoy.addClass("invisible");
			}
			
			//stick the element to the bottom of the parent if the elements position is overthe original 
			if (stayDown) {
				$decoy.removeClass("invisible");
				$dom.removeClass("sticky").attr("style" ,"").css({left: origPos.left}).addClass("sticky_bottom");
			} else {
				$dom.attr("style", "").removeClass("sticky_bottom");
			}
		}
	});
}

Usage

Use Javascript expects a dom object to be passed to it, like such:

$(document).ready(function() {
makeSticky($("#demo"));
});

Make a comment

Contribute to this article and have your say.