Pinterest Stumbleupon Whatsapp
Ads by Google

how to make sticky headerAbout a month ago, we introduced a new interface element to MakeUseOf – a floating navigation and search bar. The feedback we’ve been getting is almost entirely positive, internal search traffic has rocketed, and some readers having been asking about how to make one for their own site, so I thought I’d share.

We’ll use jQuery to stick the bar to the top of the screen – but only past a certain point. I’ll do all this in the default WordPress theme – Twenty Eleven, though of course it can be applied to any theme or website which you sufficiently understand how to modify.

The HTML

First up, open the themes header.php and identify the navigation bar that we’ll be making sticky. As I said, the code below is for the default twenty-eleven; yours may vary.

<nav id="access" role="navigation">

Firstly, add a new DIV container surrounding this entire NAV section.

<div id="access_container">
<nav id="access" role="navigation">
...
</nav>
</div>

Also, let’s move that default search bar into here. You’ll notice it’s added by default to the top right of the theme; find the line <?php get_search_form();?> and paste it into our navigation section. Delete all other instances of it in this file.

how to make sticky header

Ads by Google

If you save and refresh now, you’ll see the search form doesn’t actually appear in the navigation bar – it still shows in the top right. That’s because it’s been positioned absolutely with CSS, and we’ll be deleting all that in a second.

The CSS

Open up the main style.css file and find the section for the search form:


#branding #searchform {
...
}

Replace whatever is inside that (should be able about four lines, including some absolute positioning) with this:


#branding #searchform {
float:left;
background:white;
margin:7px ;
}

Feel free to adjust the colour or margin. Change the float if you’d rather it appeared on the right of the bar. In this theme, the search is set to expand when the user clicks inside it; that’s out of the scope of this tutorial, but you can see a similar effect on our MakeUseOf Search.

jQuery

If you’re wondering why we’re using jQuery to do this, it’s simple: CSS is fixed, and cannot be dynamically adjusted. While we could use CSS to make a sticky header, it would need to be the top element on the page. The problem we have is that our menu is not the top element, so we can’t start off with it being sticky. This is where the jQuery is used; we can check when the user goes past a certain point; then, and only then, make it sticky.

Start off by adding jQuery to your theme. Your theme may already have it loaded; if not, no worries. You can either enqueue it, by adding the following code to your functions.php, like so:


<?php
function my_scripts_method() {
wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', 'http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js');
wp_enqueue_script( 'jquery' );
}
add_action('wp_enqueue_scripts', 'my_scripts_method');
?>

Or you can just bypass WordPress altogether and hardcore this into the header file. Somewhere in your head section, just add this line:


<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js?9472a0" type="text/javascript"></script>

If you use the first method, it’ll be loaded in noConflict mode, which means you’ll need to use “jQuery” in your code to access jQuery functions. If you use the second method of directly adding it to your header, you can use the standard jQuery accessor of $. I’ll assume the second method in the code below.

So, to add some actual jQuery code, place the following somewhere at the end of your header.php – I’ve placed mine just before the <div id=”main”>


<script type="text/javascript">
//make the nav sticky
var stickyHeader = $('#access_alias').offset().top+288;
$(window).scroll(function(){
if( $(window).scrollTop() > stickyHeader ) {
$('#access').css({position: 'fixed', top: '0px'});
} else {
$('#access').css({position: 'static', top: '0px'});
}
});
</script>

The first thing the script does is to figure out where the navigation bar starts off at, and remembers that value. Secondly, we attach to the scroll event – this means that every time the user scrolls the page, we can run this block of code. When the code runs, there are two ways it can go:
1. If the window has scrolled past the navigation bar, we make it a fixed CSS (this is the “sticky” part).
2. If the top of the window is higher than the original position of the navigation bar (ie, the user scrolled back up again), we put it back to the default static position.

sticky header bar

There are two points I want to draw your attention to:

  • The +288 is in there to fix the bug of getting an incorrect position; without it, the bar is triggering its sticky state too soon – remove it to see what I mean. This won’t be neccessary in all themes, and you can probably come up with a better solution.
  • To fix the problem of the navigation bar changing width when it goes into the sticky state, edit the style.css, line 550, to read 1000px instead of 100%

That’s it, your navigation bar should now be nicely sticky.

how to make sticky header

Summary:

The full replacement header.php code for this tutorial can be found at this pastebin; and the replacement style.css here . I hoped you’ve enjoyed this little tutorial; if you’re having problems, do post in the comments or ask away at MakeUseOf Answers, but please remember to make your site publicly accessible so I can go along and have a look myself. If you’re new here, be sure to check out all our other blogger and web development articles.

  1. Steve
    March 3, 2013 at 2:30 pm

    Great help, I've got it working but a couple of bugs

    The menu items jump a little to the right when it becomes sticky. Any ideas?

    I also have issues with the right edge of the menu spanning to the edge of the screen when it becomes sticky too. I didn't change the style.css line to 1000px as in your example as it breaks on smaller screens, is there another way to constrain the width of the sticky menu?

    Finally, I get problems with the menu hiding behind the admin-bar for logged on users.

    • Muo TechGuy
      March 4, 2013 at 8:34 am

      Can you post a link? I've not been able to solve the logged in user thing, but th screen width should be fixable with some CSS tweaks.

      • Steve
        March 14, 2013 at 10:34 am

        Sorry, forgot to include that bit!

        http://sharlandmountaineering.co.uk

        Cheers!

        • James Bruce
          March 14, 2013 at 10:51 am

          Hmm, sorry Steve, 1000px is about the best I can get; on smaller screens , you'd need some responsive CSS to deal with it accordingly I think. Responsive CSS is something I utterly fail at.

  2. Stina
    December 11, 2012 at 9:42 am

    Thanks for the tip! This is just what I'm looking for, and installed a sandbox with Twenty Eleven just to try it (http://publit.stinalofgren.com/) – but can't get it to work, despite having done all the steps. Hm... what did i miss?

  3. Anonymous
    October 27, 2012 at 4:09 am

    Very Cool tip

  4. Kailith
    October 11, 2012 at 8:33 am

    I implemented this for a WordPress blog and it works on Chrome and Safari, but not Firefox. Has anyone else run into this problem? Is there a fix for it? I'd appreciate some help.

    Thanks!

    • James Bruce
      October 11, 2012 at 8:41 am

      firefox has some pretty aggressive caching policies - did you make sure to clear all your caches etc first? If so, share the URL, we can take a look.

      • Kailith
        October 11, 2012 at 6:55 pm

        This site is still very much under development, so keep your hard hat on - http://fnfweb.com/playground/

        The two problems that I've noticed are that 1. Like I've already mentioned, it doesn't work in Firefox (not a cache issue, have cleared it and re-loaded multiple times), and 2. In Chrome, about 60% of the time I load the homepage some of the content doesn't load (the dynamic portfolio and testimonials content- but the headers and static stuff loads fine). The same goes for an instance of WooSlider that appears on the primary sidebar. It doesn't load a lot of the time. I know that the fix is related to something about what I've done in the header to make the bar sticky, because I stripped all of that out and it stopped happening. I don't really know what would cause it though, and that issue in particular seems to be isolated to Chrome.

        Thank you for the help : )

        • muotechguy
          October 12, 2012 at 7:44 am

          I dont know if you fixed this already, but it's actually working fine for me in Firefox (mac, anyway), with no console error.

          Crazy idea, but could be related to you being logged in, and WordPress loading conflicting versions of jQuery for the admin toolbar. Be sure to logout first, then try again to confirm.

        • Kailith
          October 27, 2012 at 3:30 am

          So the problem was outdated Firefox (dumb, I know). I updated it and now it works.

          It's creating a problem with keeping the slideshows and homepage content from loading in Chrome and Firefox, but it works in Safari. When I strip the sticky bar code from my header, all of it works. I'm using a WooTheme as the base, so I took it to their support but they just said to take the code out and they couldn't do anything about the incompatibility. Do you have any idea of how to fix it, or why this would happen in only two of the broswers, and the two which arguably are supposed to be the best ones at that? I would appreciate the help, because I'd really love this functionality.

        • Kailith
          October 27, 2012 at 3:32 am

          So... I turned off Cloudflare on the domain and now it works? That's bizarre...

        • Kailith
          October 27, 2012 at 4:02 am

          Damnit; I broke it : [

          Now the sticky bar doesn't work, but everything loads. If you happen to feel like helping me troubleshoot, please email me. I know this is getting too ridiculous for your public comments, so I'll stop loitering trying to get a fix here. Thank you for the tutorial regardless! I've shared it where I could : )

        • Muo TechGuy
          October 27, 2012 at 7:52 am

          Ok, you have a jQuery conflict. So in the code I posted in this tutorial, just change all instances of "$" to "jQuery" and it *should* work.

        • Kailith
          October 30, 2012 at 1:12 am

          I tried that before, it didn't work. I tried it again and it still doesn't. There are other instances of the $ in my header file, so I think it should work with your code, but the only way I got it to show up was through importing the jQuery through Google (which caused the other jQuery problems). Adding the snippet to functions.php doesn't do anything, and it doesn't work without the Google code- so I'm at a loss.

        • Muo TechGuy
          October 30, 2012 at 10:12 am

          Got it: you're currently loading the script before the #top div element has been created, so it's unable to read the position. This is progress. Wrap my script in a doc ready wait thing:

          jQuery(document).ready(function(){

          //make the nav sticky
          var stickyHeader = jQuery('#top').offset().top+1;
          jQuery(window).scroll(function(){
          if( $(window).scrollTop() > stickyHeader ) {
          jQuery('#top').css({position: 'fixed', top: '0px'});
          } else {
          jQuery('#top').css({position: 'static', top: '0px'});
          }
          });

          });

          et voila!

        • Kailith
          November 1, 2012 at 5:30 am

          That worked. You are my HERO! Thank you so much- you were above-and-beyond helpful : D

  5. Anyone
    October 5, 2012 at 5:13 pm

    How to make for Blogger? pls reply sir

    • Muo TechGuy
      October 7, 2012 at 8:59 pm

      Apologies, I don't use blogger. If you follow the tutorial and are competent with coding then you should be able to achieve exactly the same on a blogger template with a menu bar.

      • Bhavik
        October 8, 2012 at 6:34 pm

        sir i want to create a technology , pc softwares, tricks's blog, sir please suggest some good names.... waiting please

        • Muo TechGuy
          October 8, 2012 at 7:36 pm

          Names? Like, domain names? That's deviating a little from the topic of the article I think. Please ask for suggestions in our MakeUseOf Answers site; http://www.makeuseof.com/answers , I'm sure you can get lots of ideas there.

  6. Nikia
    October 4, 2012 at 12:41 am

    Thank you this was so helpful!

  7. Martin
    October 2, 2012 at 9:12 am

    what a timely post - I have been looking for exactly that... unfortunately, it does not load make the nav fixed for me, even though I am using a vanilla twenty eleven theme and the jQuery seems to load properly (cut/paste): http://goo.gl/DRP4m

    • muotechguy
      October 2, 2012 at 9:25 am

      Hi Martin - you've loaded jQuery in compatiblity mode (via wordpress, perhaps another plugin is loading it for you); that means that instead of "$" in the code, you'll need to write "jQuery" instead.

      • Martin
        October 2, 2012 at 10:00 am

        wow - what a quick reply!
        with the code you mean the javascript that needs to be put into the header?
        I had tried that as well but it does no have any effect. what does have an effect is if i omit the 288px offset - in that case, the social slider does not slider anymore. however, i did not have that one active prior as well and the menu would still not slide...

        • muotechguy
          October 2, 2012 at 10:02 am

          Yes, the script in the header - change all the $ to jQuery. That should fix it. If not, make the changes then I'll check the error log again on your site.

        • Martin
          October 2, 2012 at 10:17 am

          I have already done so - yet the navbar will not float...

          nevertheless, already given like and +1... anything else i can do to support your support?

        • James Bruce
          October 2, 2012 at 10:23 am

          Thanks for the support Martin; i foudn the error though. Change this line:

          var stickyHeader = $('#access_alias').offset().top+288;

          to
          var stickyHeader = $('#access').offset().top+288;

          (with jQuery modifications instead of $ too). Sorry, bug in my code I didn't update apparently.

        • Martin
          October 2, 2012 at 10:39 am

          excellent - yes, it does float now... i really could have seen that as well...

          what it however does now is to appear quite late (in comparison to your hover) and the menu bar gets distorted with the right align far out of visibility... any suggestion on how to combat that?

        • James Bruce
          October 2, 2012 at 10:50 am

          Yes, the lateness is because of 288px fix; that was for the default header image, reduce that if you dont have as tall a header...

          The additional width I fixed by making it a fixed 1000px instead of 100%; however, its no longer responsive so smaller width devices will break it. Let me know if you come up with a more elegant solution though...

        • Martin
          October 2, 2012 at 11:37 am

          alright - I'll have a look at the CSS tomorrow and see if that will fix it...

  8. elhaj
    October 1, 2012 at 5:22 am

    would apreciate a way to remove that sticky stuff

  9. wilL Toxic
    September 30, 2012 at 9:03 am

    thank you, thank you
    something i would like to use.

  10. Dimal Chandrasiri
    September 29, 2012 at 7:06 am

    very cool article! thanks !: )

    • Dimal Chandrasiri
      September 29, 2012 at 2:23 pm

      it would be great if you can make the top menu sticky since we have scroll all the way up to get it! :)

  11. Rahul
    September 28, 2012 at 9:55 pm

    i see you are using sublime text..i think i would to love to have your next article on this editor..probably your opinion

  12. Jack Hecker
    September 28, 2012 at 9:47 pm

    This is very cool!

  13. Joel Lee
    September 28, 2012 at 6:08 pm

    Cool beans. As someone with no jQuery knowledge, that was pretty interesting.

Leave a Reply

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