I’ve got no clue as to when but at some point I reached a tipping point where I began writing more of my own JavaScript (well jQuery really) rather than taking the easy option and looking for a plugin.
There’s two reasons why I started to do this…
One such function I’ve been refining this week makes a sidebar element track with the scrollbar; making it appear sticky. I’ve used the basis for this function a couple of times before but each time I come to reuse it I’ve ended up scratching my head trying to figure it out again.
This time I wanted to simplify it, make it a little more reusable and also comment the code better.
Position:fixed
is the simple way to fix something in relation to the browser window but often a website has headers and footers that you don’t want the fixed element overlapping. Also responsive design can add an additional complication; as it often does.
Below is the code needed to build the sidebar and get it all sticky, but for a working example go to our Google Penalty Recovery page.
<div class="twocol--outer"> <div class="twocol--main"> Your Content </div> </div> <div class="twocol--side"> <div class="sidebar sticky"> </div> </div>
.twocol--outer {float:left; margin-right:-280px; width:100%;} .twocol--main {margin-right:280px; padding-right:60px;} .twocol--side {float:right; width:280px;} .fixed {position:fixed;}
$(document).ready(function(){ var $stickybox = $('.sticky'); // The element that needs to move var $sibling = $('.twocol--main'); // The area the box needs to scroll against var $margin = 40; function sticky(){ $stickybox.removeClass('fixed'); // Reset class $stickybox.removeAttr('style'); // Reset style before adding new // Resets appear here so we can get the height and width as it is when not floating var $stickyboxHeight = $stickybox.outerHeight(); // Height of element that needs to be sticky var $stickyboxWidth = $stickybox.outerWidth(); // Width of element that needs to be sticky if($sibling.height() > ($stickyboxHeight + $margin) && $(window).height() > ($stickyboxHeight + $margin) && $stickybox.parent().css('float') != 'none'){ // If sibling is taller than box && window is taller than box && box parent is not floated (no point fixing if it's in a single column layout) var $leftpos = $stickybox.offset().left; // Left Coords var $startPoint = $sibling.offset().top - $margin; // Point it becomes fixed + default margin to top var $stopPoint = ($sibling.offset().top + $sibling.height()) - ($stickyboxHeight + $margin); // Point it stops and tracks bottom border of sibling = bottom of sibling + (height of box + margin) if($(window).scrollTop() > $startPoint){ $stickybox.addClass('fixed'); // Add class $stickybox.css({ 'left' : $leftpos, // Set left position to match when not sticky 'width' : $stickyboxWidth // Set width incase inherits width from parent }); if($(window).scrollTop() > $stopPoint){ // When sticky can't go any further $stickybox.css('top',($stopPoint - $(window).scrollTop() + $margin)); // top = bottom of sibling - amount scrolled + default margin }else{ $stickybox.css('top',$margin + 'px'); // Default margin from the top when is sticky } } } } sticky(); // Run on load window.onscroll = function(){ sticky(); // Run on scroll } window.onresize = function(){ sticky(); // Run on resize } });
I’m hoping the comments within the code are enough to explain what’s going on rather that covering each line in detail. But as an overview the code has to do a few things:
For the last of that list we determine a two column layout on whether or not an element is using the CSS float property. We could use Media.match to specify an exact screen size but that leads to repetition and extra overhead if changes are made to the breakpoint used at a later time.
Feel free to go and use the code in your own website, it’s not a one size fits all solution and there’s changes you’ll have to make to suit your own requirements. For example you’ll need to tweak it if you want the element to appear fixed to the bottom of the window rather than the top. But if you’ve got a question, or an idea to improve the code add a comment below.
Right now I’m just happy it works and it’s a lot less code than similar plugins.
Image courtesy of Gabriel Toro
Like what you’ve read, then why not tell others about it... they might enjoy it too
If you think Bronco has the skills to take your business forward then what are you waiting for?
Get in Touch Today!
Discussion