Headway Themes is turning 5! Use coupon headway5 to save 35%. See Pricing →

Creating a "Sticky" Navigation Bar with Headway

sticky_nav_feature

VIEW the DEMO

PROBLEM: Your navigation is one of the most important parts of your website. It’s how your visitors get from the homepage to other parts of your site! But once they scroll down to read your content, they can’t see the navigation anymore – and darn it, you want them to see it all the time!

SOLUTION: A sticky navigation bar. You see them all the time (not a Headway site), but how to implement? No worries; it’s actually pretty easy!

Step 1: Set up a WordPress & Headway site with a navigation bar.

Yeah that’s as easy as it sounds. If your site is already completed or in progress, you probably have a navigation bar. If you don’t, go ahead and add a navigation block now.

Step 2: Add a little jQuery Magic

This jQuery script is pretty well commented, but here’s the gist of it:

  1. Hi webpage! Are you being displayed on a mobile device? If you are, we won’t make the navigation sticky because dang, a sticky nav on a mobile device takes up too much room. Oh, you aren’t? Fabulous.
  2. Oh, the window is scrolling! That’s my cue. I’m looking for the .block-type-navigation class. You got one? You do? Fabulous! I’d like to add  a class to it, please. Thanks!
  3. Whoops, you scrolled back up the top. Let’s remove that class, huh? Thanks!

Basically once you scroll down, we are sticking the navigation to the top of the page & making it super obvious to the user that Hey! You! Can! Navigate! There’s more to see!

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
 //STICKY NAV
 var isMobile = {
 Android: function() {
 return navigator.userAgent.match(/Android/i) ? true : false;
 },
 BlackBerry: function() {
 return navigator.userAgent.match(/BlackBerry/i) ? true : false;
 },
 iOS: function() {
 return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
 },
 Windows: function() {
 return navigator.userAgent.match(/IEMobile/i) ? true : false;
 },
 any: function() {
 return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
 }
 };
//Calculate the height of <header>
 //Use outerHeight() instead of height() if have padding
 var aboveHeight = $('.top-row').outerHeight();

 //when scroll
 $(window).scroll(function(){

 //if scrolled down more than the header’s height but this isn't mobile
 if ($(window).scrollTop() > aboveHeight && !isMobile.any()){

 // if yes, add “fixed” class to the <nav>
 // add padding top to the #content
 // (value is same as the height of the nav)
 $('.block-type-navigation').addClass('fixed').css('top','0').next()
 .css('padding-top','42px');

 } else {

 // when scroll up or less than aboveHeight,
 // remove the “fixed” class, and the padding-top
 $('.block-type-navigation').removeClass('fixed').next()
 .css('padding-top','0');
 }
 });
});
</script>

A Note on Loading jQuery

This code goes straight into the Header Scripts area of Headway -> Options. The first line ensures that jQuery is being loaded. If you are using a child theme & can load the script via the wp_enqueue function, that’s the preference and you can skip that line!

You could also skip the first script line in the code above (and start at the second < script >
tag), and put this line of code in the Footer Scripts area instead to load jQuery more cleanly. This will prevent jQuery from being loaded twice (and could fix any potential errors).

<?php
wp_enqueue_script('jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js', false, false, true);
?>

Two Additional Notes!

Multiple Navigation Blocks: As written, it is going to affect *all* of your navigation blocks. SO if you have two of them on a page, it’s going to look for both! If you want only one of the navigation bars to be affected however, that’s no problem. Just add a custom class to your navigation block (open up the Block Options for the navigation block, and add something in the Config -> Custom Classes input). Then you’ll replace .block-type-navigation with .[yourClassGoesHere]. So if you gave your block a class of stickyNav, your jQuery code would read something like: $(‘.stickyNav’).addClass(‘fixed’).css(‘top’,’0′).next() instead of $(‘.block-type-navigation’).addClass(‘fixed’).css(‘top’,’0′).next(). Remember, there are two places this gets changed in the script!

Taller Navigations Blocks: By default this script is set for a navigation block that is around 42px high. If your navigation block is taller/shorter and this isn’t behaving the way you expect it to, change the line that says ” .css(‘padding-top’,’42px’);” — you’ll change 42 for the height of your navigation block.

Step 3: Add a Little Custom CSS Magic

Finally we need just a teeny little bit of CSS to make this look fabulous & for it to stick! In Design Mode, open up the Live CSS Editor and drop in this code:

.fixed {
     position:fixed !important;
      left: 0;
      text-align: center;
}
.fixed .block-content {
      display: inline-block;
      text-align: left;
      width: 940px; /* This should be the width of your grid!!! */
      float:none;
}

The only part of this you’ll need to change is the width — that should be equal to the width of your grid.

Step 4: You’re done!

Aside from lording it over your friends that you just created a sticky nav … you’re all set! Post your site in the comments so we can see how great your site looks!

Spread the word!

66 Responses

  1. WeekendProducer says:

    I sent demo page to my Android device and the page is shown in the same way as on the desktop. Nothing changes. It doesn’t “response” to my mobile.

  2. ramonahux says:

    Hi, 
    Is there a tweak for this that would allow a separate menu to appear upon scrolling down? 
    Such as here: http://www.interviewmagazine.com/#_
    and here: http://apairandasparediy.com/
     
    Mona

    • @ramonahux You would want to target a different navigation block, one that you hid from view by default using CSS or the Responsive Grid block hiding. See my note about multiple navigation blocks for a tip on how to target a specific navigation block.

      • ramonahux says:

        @caitlinheadway  @ramonahux Thank you for your response. Where would I find the responsive grid hiding?

        • ramonahux says:

          @caitlinheadway I do not seem to have the Resposive Grid option to hide a block in the config. Would you be able to point me towards some CSS to hide the block by default?

      • ramonahux says:

        @caitlinheadway Hi Caitlin,
        I’ve tried this with responsive grid hiding but it doesn’t work. The navigation bar merely remains hidden. Is there any CSS you could provide to initially hide the second bar until the user scrolls down?

        • @ramonahux sorry I got all these notifications at the same time :-D 
           
          You need to add an extra line to the CSS for the .fixed class above - 
           
          .fixed {
          position:fixed !important;    
           left: 0;      
          text-align: center;
          display: block !important;
          }

        • ramonahux says:

          @caitlinheadway Hi Caitlin,
          Sorry about this. But I have turned on Responsive Grid hiding and entered all the code as above but it isn’t working. The second menu stays either completely hidden (when responsive grid hiding is on) and doesn’t appear on scroll or (when responsive grid hiding is off) is constantly present…

        • @ramonahux I think we’re geting into “I would need to see the site” territory :-D

  3. afroniquely says:

    YAYYYYYY!!! Thanks so much @caitlinheadway I will be trying this and I am hoping for good results. I like @ramonahux would love to know how to make them separate. So say on my site, I would just have two separate menus? The main menu and then another one that would be the pop-up overlay menu? But I would have to hide it you say via responsive grid hiding? Not sure how to target the right one and also make it appear and such.

  4. GetGoHelp says:

    Nice and useful tut. :)
     
    So the Jquery code?  We have to insert the code you show us into the header option of Headway?
     
    Thanks :)

  5. LeftoverCake says:

    Firstly, thank you for the code. Your explanation was very clear… It took a little tweaking around with but I was able to get it to work…
     
    My question is how hard would it be to “brand” the floating nav-bar with a logo that floats to the left or right of the menu text or maybe social icons? Should this be feasible? Or is this treading into the ‘extraneous coding’ area? Thanks in advance for any pointers! :)

  6. cosmintataru says:

    Hello,
     @caitlinheadway 
    Thanks for the tip, however it is not working for me. Please see http://www.windowsfaralimite.ro. I would really love to get it working ! Please help

  7. cosmintataru says:

    Hello !
    One small suggestion: add z-index:100; under the .fixed class to make sure the menu is always on top. :)

  8. I am using Tabsplus in my site and there are conflict issues
    If I put the jquery link in the header, tabsplus does not work, if I put jquery link in the footer the menu does not work on the pages that Tabsplus is not on.
    Any ideas?

  9. richardvav says:

    Using the above as soon as you start to scroll the menu becomes sticky, I guess because the class .top-row doesn’t actually exist so you should switch from using the class .top-row to using the actual header element that way it only switches to sticky when the actual height of the header element has been scrolled and not before
    var aboveHeight = $(‘.top-row’).outerHeight();
    should be
    var aboveHeight = $(‘header’).outerHeight();

    • richardvav Good point Richard :) I was using a .top-row in my dev environment at some point but failed to explain that part of my code :) 

      If your navigation is not at the top of the screen, you’ll want to change the line there based on the element above the navigation, like .block-type-header (.header won’t do anything unless you define a custom class)

  10. champen says:

    slideshow shows in front of the menubar and hides it when i use this?

  11. Ben S says:

    (Apologies for the massive post) I was searching around for something like this and came across a few different scripts, and I think I may have found a simpler way of toggling the class and calculating when to switch the class. This way it calculates where the top of the main-nav (custom class) is and switches the class when the window reaches it. It doesn’t affect the navigation wrap either (which was causing my layout to jump around before), instead it leaves the wrap and moves the .block-content.
    I also kept the first part of your script to check for mobile devices and added it in.
    My only problem is that the submenu drop down animation seems to have stopped working – so, I’m not sure if I’m loading jQuery properly? I tried taking out the first line and adding that other script to the footer like you suggest, but it seems to stop this script from working?
    This is the first time I’ve played around with jQuery properly, so I’m not 100% sure if this is better or not? Here’s the script I’m using (and a demo in jsFiddle: http://jsfiddle.net/zZUMS/5/):

    <script src=”//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js”></script>
    <script type=”text/javascript”>
    //STICKY NAV
    //when window scrolls
    $(document).scroll(function() {
        // CALCULATE distance of main-nav from top of viewable window
        var menuTop = $(“.main-nav”).offset().top; – $(window).scrollTop();
        //if scrolled down more than main-nav & not mobile then toggle class
        var useStickyNav = $(document).scrollTop() > menuTop  && !isMobile.any();
        $(‘.main-nav .block-content’).toggleClass(‘sticky-nav’, useStickyNav);
    });

    </script>

  12. theDesignCreative says:

    Hey, great tutorial, and well needed. I have three menus on this page http://www.15eightyone.com/fyf/category/2009  but only want to target the last 2. What would I need to do?

  13. Lazlo Toth says:

    Thanks for your post. I have a couple of questions. I viewed your demo
    on two different browsers (FireFox 19 and Safari 5) and it looks pretty
    messed up and unprofessional in the way that it jumps when you start to
    scroll. Is this normal? Also, why do I see two copies of your header
    when I scroll…and why is one of them transparent. Here is a screencast
    that shows exactly what I am describing: https://www.youtube.com/watch?v=OhKUMaYM-DQ

  14. surjithctly says:

    here is an interesting approach to Sticky navigation, Only shows navigation when user really wants to be.. http://web3canvas.com/item/sensitive-sticky-navigation-with-jquery/

  15. praveen_ramachandran says:

    Well, I’ve to add z-index: higher-number to make sure that the header isn’t looking messed up like a see through glass. This must be the ‘messed up’ aspect in the comment by Lazlo.

  16. nicolasbesserer says:

    Great post!

    However, I simply can’t get it to work in responsive mode… it´s still there when in responsive mode, and the “responsive menu” is gone… ?

    Any solution to this problem?

    Thanks…
    /Nicolas

    • Clay Griffiths says:

      Hey Nicolas,

      Thanks for commenting!

      Please create a thread in the support forums under the customization category. Be sure to reference this blog post and include the URL to your site and we’ll get this working for you :-)

  17. jlundie says:

    Awesome tutorial – thank you!

    Is there a tweak that I need to make to the CSS if I want to group three blocks together under a custom CSS tag for the jquery call, but still have them hold their position relative to each other?

  18. Jonny Zavant says:

    Just implemented the code in under 5 minutes, and now the nav bar does exactly what I wanted it to do. Thanks for the super helpful directions!

  19. jos vermeulen says:

    I (think) I’ve done exactly as instructed (1. load first code block, except first line, in the header scripts location, 2. load jQuery in the footer scripts location, 3. add css and adjust size of grid) and it doesn’t do anything. What else should I do?

  20. Is it possible to stick a fixed wrapper?

  21. Jason Hull says:

    Why not build this in as a feature? Seems pretty popular as of late.

    • Clay Griffiths says:

      Hey Jason,

      It’s already possible to do this now in Headway without any additional code. You can simply set the Navigation wrapper to Position: Fixed in the Nudging panel in the Design Editor and then add the necessary margins to the other elements (since the navigation is fixed it won’t push any elements down) and you’ll be set.

      This is something we’ve been looking into to see if we can make it any easier.

      Thanks for the feedback!

      • sylvainbe says:

        Hi Clay,

        I’ve tried your method and it works fine.

        Is there a way to hide the fixed bar when on a mobile device so it doesn’t take all the place ?

        Thank You

  22. Shanthony Exum says:

    http://ashleyrosehardy.com/?page_id=9
    It seems like the nav is jumping around quite a bit. Is there a way I can make it smooth?

  23. jon Siddall says:

    This is a great method to add Sticky nav to Headway
    http://www.wawrzyniak.me/richard/sticky-navigation-bar/
    Worked perfectly first time, just remember if your logged in the wordpress menu will hide the sticky menu. So check the results in another browser that’s not logged in.

    CSS
    .fixed {
    position:fixed;
    top:0;
    z-index:9999;
    }
    .fixed2 {
    padding-top:32px; /*change value to suit your layout*/
    }

    Script (put in footer)

    jQuery(document).ready(function() {
    var row1Height = jQuery(‘header’).outerHeight();
    jQuery(window).scroll(function() {
    if (jQuery(window).scrollTop() > row1Height) {
    jQuery(‘nav’).css(‘max-width’, jQuery(‘nav’).outerWidth() + ‘px’);
    jQuery(‘nav’).addClass(‘fixed’);
    jQuery(‘.row-3′).addClass(‘fixed2′);
    } else {
    jQuery(‘nav’).removeClass(‘fixed’);
    jQuery(‘.row-3′).removeClass(‘fixed2′);
    }
    });
    });

  24. wnikzad says:

    This was really good,
    I followed the steps and succeeded to make my main menu sticky after scrolling.
    but it works only at homepage. In other pages it breaks and disappears behind some other divisions, however I assigned the highest z-index value, float:none; overflow:hidden; clear:both; to it in css, but didn’t work. I think there’s some conflict.
    Any help would be appreciated.

  25. AWN says:

    Hello dear,
    It was really great!
    I’m new to jQuery, it works fine in Chrome and IE but not in Firefox.
    When I add the first script, the one which loads the jQuery, it works in Firefox too but crushes other elements like my slider (I have one slider it stops it).
    However I’ve added the PHP code you mentioned in the footer, but not fixed.
    Any direction would be appreciated.

  26. Frank Gomez says:

    I’d like to see this modified http://www.wawrzyniak.me/richard/sticky-navigation-bar/ to work for a wrapper (nav in it’s own wrapper)
    I have it “kind of working” on a site (new.zollingermediation.com) but it isn’t pretty.

    • Frank says:

      I did my best to modify this for wrappers too. I like bar all the way across)
      In other words like this: new.zollingermediation.com (if you don’t find this page you can go to zollingermediation.com)

      THis is the script from http://www.wawrzyniak.me/richard/sticky-navigation-bar/ tweaked
      (it isn’t perfect because of width of Navigation when screen is reduced), working on it.

      jQuery(document).ready(function() {
      var row1Height = jQuery(‘header’).outerHeight();
      jQuery(window).scroll(function() {
      if (jQuery(window).scrollTop() > row1Height) {
      jQuery(‘nav’).css(‘max-width’, jQuery(‘nav’).outerWidth() + ‘px’);
      jQuery(‘nav’).addClass(‘fixed’);
      jQuery(‘#wrapper-5′).addClass(‘fixed2′);
      } else {
      jQuery(‘nav’).removeClass(‘fixed’);
      jQuery(‘#wrapper-5′).removeClass(‘fixed2′);
      }
      });
      });

      body.custom .fixed {
      position:fixed;
      top:0;
      z-index:9999;
      }
      body.custom #wrapper-5.fixed2 {
      position:fixed!important;
      top:0!important;
      z-index:9999!important;
      padding-top:48px;
      }

    • frankiet says:

      I think I’ve perfected it Use script from above with this CSS
      (Note I’ve tried about 6 ways to do a sticky wrapper and none consistenly work until this one).
      body.custom .fixed {
      position:relative;
      top:0;
      z-index:9999;
      }
      body.custom #wrapper-5.fixed2 {
      position:fixed!important;
      top:0!important;
      z-index:9999!important;
      box-shadow:0 1px 4px #000;
      }

  27. Nkenge says:

    Sticky Navigation works GREAT!
    JUST ONE ISSUE!
    The drop down submenu feature only works when I’m at the top of the page. As I scroll down, the submenu won’t show. Can someone please help me?

  28. Great article and good explanation.

    It is worth clarifying that if you have the menu on a wrapper, then you should work on the wrapper block and not on the navigation block.

    • Jamie VanRaalte says:

      There is no wrapper block but a navigation block will always be in a wrapper. It’s up the designer/developer if they want the entire wrapper to stick or just the block.

  29. Jay says:

    Thanks for the usefull tip.. Is there also a way for it to also work on mobile phones? I am a beginner in CSS. I used the responsive menu that goes dropdown mode in mobile phones and I want the dropdown menu to also be sticky in the phone when scrolling down. If there is an easy way to do that please let me know.

    Peace and love

    • Clay Griffiths says:

      We’re planning on integrating sticky navigation bars into the core of Headway and it will be responsive.

      Sorry for not having an immediate solution!

  30. Shaun Oster says:

    I have a much better solution. I did this, it worked but a bit clunky. This solved EVERYTHING, for multiple headway issues. Including woocommerce basket!!!
    http://codecanyon.net/item/mega-main-menu-wordpress-menu-plugin/6135125
    Super configurable, and it sees your headway nav blocks and takes them over!

  31. e says:

    code doesnt work, navigation bar becomes the size of full screen when i scroll

  32. maryssa hicks says:

    Is it possible to create a sticky nav when you scroll past it or under an element? Like if my nav is under a header, and once i scroll past the header the navigation becomes sticky?

    Like here:
    http://themeforest.net/item/jarvis-onepage-parallax-wordpress-theme/full_screen_preview/5370691

  33. rinky says:

    First step (putting the code into the header scripts) kills my image slider (meteor). Is there an updated tutorial for this?

  34. Loz says:

    I’ve added a sticky nav bar but when scrolling my blocks > content > body text >
    goes on top of the sticky nav. See http://www.lozbar.com/about
    I’ve tried changing the behaviour to ‘stay in the same position as you scroll (fixed)’ but that doesn’t do anything.
    i just copied and pasted the long code above for the sticky nav and also the code for the design mode and changed the width.

Leave a reply

Current day month ye@r *

Headway Newsletter

Get the latest updates from our blog directly in your inbox! Are you ready to learn the latest from Headway Themes?

Copyright © 2014 Vesped Inc. All Rights Reserved. Proudly Powered by Headway and WordPress