Freebie: Sticky Bootstrap navbar on scroll for Bootstrap 4

The release of Bootstrap 4 will see the end of the affix plugin leaving developers & site builders needing to find an alternative for their fixed navbars and elements. We’ll be covering a complete solution in a future article but in the meantime we’ve put together a quick solution for Bootstrap 4 Sticky Navbars.

This is a really quick & simple alternative to the affix plugin for Bootstrap navbars in Bootstrap 4, so let’s jump straight in!

The HTML

You can use the default navbar component and simply add data-toggle="sticky-onscroll" which we’ll use to invoke our Javascript.

<nav class="navbar" data-toggle="sticky-onscroll">
   <div class="container">
       <div class="navbar-header">
            <a class="navbar-brand" href="http://bootbites.com">BootBites.com</a>
        </div>
   </div>
</nav>

Javascript

Our Javascript first looks for the data-toggle="sticky-onscroll" element then we insert a wrapper element (stickyWrapper) right before the navbar element. The stickyWrapper allows us to see the “true” top offset of the .navbar element as once it’s fixed or sticky it top offset is altered meaning we wouldn’t be able to return it to it’s original position.

We then bind a function (stickyToggle) to all scroll and resize events which happen on the page, this stickyToggle function checks to see it the .navbar element is at the top of the page and if it is it adds the class is-sticky and sets the height of the stickyWrapper element so the content doesn’t jump up when the navbar is sticky.

$(document).ready(function() {
  // Custom 
  var stickyToggle = function(sticky, stickyWrapper, scrollElement) {
    var stickyHeight = sticky.outerHeight();
    var stickyTop = stickyWrapper.offset().top;
    if (scrollElement.scrollTop() >= stickyTop){
      stickyWrapper.height(stickyHeight);
      sticky.addClass("is-sticky");
    }
    else{
      sticky.removeClass("is-sticky");
      stickyWrapper.height('auto');
    }
  };
  
  // Find all data-toggle="sticky-onscroll" elements
  $('[data-toggle="sticky-onscroll"]').each(function() {
    var sticky = $(this);
    var stickyWrapper = $('<div>').addClass('sticky-wrapper'); // insert hidden element to maintain actual top offset on page
    sticky.before(stickyWrapper);
    sticky.addClass('sticky');
    
    // Scroll & resize events
    $(window).on('scroll.sticky-onscroll resize.sticky-onscroll', function() {
      stickyToggle(sticky, stickyWrapper, $(this));
    });
    
    // On page load
    stickyToggle(sticky, stickyWrapper, $(window));
  });
});

CSS

We prefer not to set CSS properties via Javascript unless absolutely essential so we need some CSS code in order to stick or fix our navbar in position once it reaches the top of the page. From our Javascript above we have 2 classes to work with:

  • sticky: element is sticky target but not yet sticky/fixed
  • is-sticky: element has reached the top of the page and is sticky/fixed, this requires position: fixed;

So our only require CSS is:

.sticky.is-sticky {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  z-index: 1000;
  width: 100%;
}

 

For polish we’ve added a bunch of transitions to our navbar element so the background colour transitions nicely to a darker shade, feel free to experiment!


That’s it, enjoy!

We’ll be covering a more complete affix plugin alternative in the coming weeks so sign up to the newsletter to stay up to date.

License

Free to use for personal & commercial projects, attribution not required but appreciated.

2 Comments

  1. Roman says:

    Hi, how this code upade when is navbar on top and i want different style for navbar when i scroll down.
    you can see here : http://it-b4.itemedia.sk/

    Thanks

  2. Chrismas says:

    Good tutorial! I have question that might reveal what a newbie I am.
    If I restrict the navbar to fit inside a container when it is in responsive (not sticky) mode, how do I keep the .is-sticky navbar from changing width when scrolling?
    Using affix in Bootstrap 3 it seemed that the .is-sticky navbar used the full body container as parent and therefore “jumped out” of the container. I never managed to fix that.
    Do you have a good solution?

Leave a Reply

Your email address will not be published. Required fields are marked *