How to create a resizing menu bar

Lately some websites, like This is the Brigade and All You, have started featuring a dynamic and animated menu that resizes on scroll down. Minimizing the main navigation to allow more space for the content. In this tutorial, I’ll explain how you can create this menu yourself with HTML5, CSS3 and just a bit of jQuery. 

This kind of menu is great if you want to give special focus on your content throughout the whole website, and it also enables you to create a bigger and more impactful navigation on a user’s first visit to a website. You can better show your website brand or logo, great for the above the fold view; and after engaging the user in a visit, a smaller and minimized version hides away subtly to let the user focus mainly on your content.

There are several ways of doing this. In this tutorial, I’ll explain how to create a full width fixed menu bar, that resizes in height along with the logo, creating a simple minimized version of the initial one. If you prefer you can also replace the logo image by another variation of your logo, such as initials or an icon, but keep in mind that consistency is really important here, so that the user understands how the element has changed and that its main purpose is still the original one; navigating the website.

Before we start, you can checkout the demo or download the source from here.

 

Creating the basic structure in HTML 

We’ll start by creating the basic HTML code we’ll need. We’ll be sticking to a really simple HTML5 structure for the starting point. 

<!DOCTYPE HTML><html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>How to create a dynamic top bar | Webdesigner Depot</title>
  </head><body>
</body></html> 

Now that our initial HTML code is done, we’ll add the code for the menu as well as some other details on the head of our HTML file. 

<!DOCTYPE HTML> <html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="author" content="Antonio Pratas">
    <title>How to create a resizing menu bar | Webdesigner Depot</title>
    <link rel="stylesheet" type="text/css" href="http://meyerweb.com/eric/tools/css/reset/reset.css">
    <script src="http://code.jquery.com/jquery-latest.js"></script>
  </head><body>
    <header class=“large”>
    <nav><img class=“logo” src="wdd.png"/>
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">Posts</a></li>
      <li><a href="#">Awesome Freebies</a></li>
    </ul> </nav>
    </header>
    <section>
      <p>Let's get that menu small!</p>
      <p>End of the line.</p>
    </section>
  </body>
</html> 

In our <head>: we added the meta tag for the author to identify the file creator; after that we included Eric Meyer’s famous reset.css that will reset almost every element in your HTML file, giving you a cleaner and easier document to work on. And since we’ll be using jQuery later on, in the final line of our head element we import it through the jQuery CDN. 

I hotlinked most files to keep the document as simple as possible, but bear in mind that if you prefer you can download the latest versions of all these files and use them locally along your HTML file, and this will prevent possible problems with version compatibilities or changes in these files in the future. 

In our <body> tag, we used the default HTML5 <header> element. Our <header> will be full width and will be responsible for the changes between large and small versions of the menu. We are giving our <header> a class named “large” so that we can change some specific properties in the CSS to turn our menu into the smaller version. The <nav> is our menu container that holds our website logo image and a simple unordered list menu with three links for our website. 

Since we don’t really have any content here, the <section class=“stretch”> is going to be used to stretch the page to force the scroll, so that we can see the menu change.

And this is about it on HTML. From now on we just need to style our elements with CSS and make the menu dynamic.

 

Styling the menu and page 

To keep this code in a single file, I’ll be creating the CSS in the <head> element. So our whole CSS will come before our closing </head> tag. 

<style type="text/css">
/* Importing Amaranth Font for menu text */
@import url(http://fonts.googleapis.com/css?family=Amaranth);
/* Basic layout */
body{ background-color: #ebebeb; }
ul{ float: right; }
li{ display: inline; float: left;} img.logo{float: left;}
/* Size and center the menu */ nav{ width: 960px; margin: 0 auto;} 

This bit of CSS will make our menu 960px wide and centered, while arranging our menu to the right and our logo to the left. We are also importing the Amaranth typeface from Google Web Fonts, to use for our text on the page. 

section.stretch{ float: left; height: 1500px; width: 100%; }
section.stretch p{ font-family: 'Amaranth', sans-serif; font-size: 30px; color: #969696; text-align: center; position: relative; margin-top: 250px; }
section.stretch p.bottom{ top: 100%; } 

Here we are just forcing the page to stretch to force the scroll, and positioning the text to indicate the beginning and end of the content. This bit is completely optional, but it will help you calculate how to align the second version of the menu with your content.

header{ background: #C7C7C7; border-bottom: 1px solid #aaaaaa; float: left; width: 100%; position: fixed; z-index: 10; }
header a{ color: #969696; text-decoration: none; font-family: 'Amaranth', sans-serif; text-transform: uppercase; font-size: 1em; }
header a.active, header a:hover{ color: #3d3d3d; }
header li{ margin-right: 30px; }

/* Sizes for the bigger menu */
header.large{ height: 120px; }
header.large img{ width: 489px; height: 113px; }
header.large li{ margin-top: 45px; }

</style>
</head>

Here we are finishing our basic header styling. The <header> will serve as our menu container. It will contain our <nav> element and will be the element where we define the background color, the menu height, menu links styles and others. It will adapt to the width of the screen with the property width: 100% and will stay fixed over the other elements on the website. It’s important to remember to set the z-index to make sure that this element will overlap the rest of the page, as well as position: fixed to make the div fixed on top, so that it will remain on the same position while the user scrolls through the website. As you can see, besides setting the styles for header, we’re also setting some specific styles for the “large” class using header.large. Our menu’s initial state will be large, and so we are defining here only the styles needed to make it look like we want as soon as the user enters the page.

 

Dynamically resizing the menu

We have our menu done and styled, but we still want to make it minimized. To create this other state, we will be creating a new class for the <header> in the CSS named “small, that will be the responsible for changing the properties we need to modify. We already defined the bigger menu, so now we just need to make our menu shorter, our image smaller in size proportionally, and the margin-top we’re using in our <li> elements must also be reduced, so that they’ll remain vertically centered with the new menu height:

/* Sizes for the smaller menu */
header.small{ height: 50px; }
header.small img{ width: 287px; height: 69px; margin-top: -10px; }
header.small li{ margin-top: 17px; }

So as you can see, these styles are almost the identical to the ones to the larger menu, we just changed the class “large” to “small” and changed the values we were using to smaller ones. We are using a negative margin-top on the image to center it in the container, since the image has a subtle shadow and is higher than the typography to accommodate it. Now we have all the necessary styles to make the menu change size, and if you try to change in your HTML <header class=“large”> to <header class=“small”>, you’ll see in the browser that the menu will become smaller. But we need this done dynamically.

Changing our menu class with jQuery

With all our styles in place, we just need to add a bit of JavaScript to make the switch between the classes “large” and “small”. Since we want to change this based on the scrolling of the user, we will be using the .scrollTop() function in jQuery. This function let us get or set the position of the scroll in pixels. The scroll position is the the number of pixels that have already been scrolled out of the browser view. In this case we just need to know how manu pixels the user has scrolled so that we can trigger our code and switch the classes:

<script type="text/javascript">
$(document).on("scroll",function(){
    if($(document).scrollTop()>100){
        $("header").removeClass("large").addClass("small");
    } else{
        $("header").removeClass("small").addClass("large");
    }
});
</script>

This is the JavaScript needed to detect when the user has scrolled. When the user has scrolled more than 100 pixels, it will remove the class “large” that we created and add our new class, “small”. This way the menu will change to the dimensions we previously defined in the CSS. Try it, by now it should work already, but you might find it too harsh changing from one state to the other.

CSS transitions to animate the menu

To make the switch between classes on our menu smoother, we’re going to be using CSS transitions. Just use this piece of code next to the rest of your CSS.

header,nav, a, img, li{
  transition: all 1s;
  -moz-transition: all 1s; /* Firefox 4 */
  -webkit-transition: all 1s; /* Safari and Chrome */
  -o-transition: all 1s; /* Opera */
}

Here we define transitions for all CSS properties for the <header>, <img> and <li> elements, basically all the elements we are changing. This code will animate the changes between both classes with CSS Transitions for 1 second. Test it now, the result should be a lot smoother.

 

It’s your turn now

Now that you’ve seen how easily this effect can be achieved, go ahead and make your own version of a resizing menu bar. You can also get more creative than me and change even more properties such as background color, text color and even size and position of the menu, and even test it with different kinds of CSS transitions, but keep in mind that your users should keep up with the changes in the menu. The menu and the website logo is usually one of the most identifiable and expected elements, and by changing it drastically you might confuse the user, so make sure to keep some coherence between both versions and always test it out with some users.

Have you built a menu like this? Do you prefer a different technique? Let us know in the comments. 

Featured image/thumbnail, accordion image via Shutterstock.

  • Piper

    The demo isn’t resizing at all.

  • http://brunoscopelliti.com/ Bruno Scopelliti

    The trick is simple, but effective … and more importantly improves navigation.
    I had not yet seen.
    Thank you for sharing

  • marvin

    thanks for sharing us this tutorial. http://www.blogussion.com/

  • http://twitter.com/SentivaWeb Sentiva

    Gorgeous! Can’t wait to try it out!

  • http://www.pinkzebradesigns.com.au/ Troy Wilson

    Amazing concept! I am looking out for such thing for one of my designing project. Thanks. I hope this trick works

  • http://www.aurisstudio.com/ Arshad Ansari

    This is really a great concept! I use top fixed navigation in my website but still they feel plain. This way I can make the navigation look more appealing! Thanks so much for sharing!
    I’ll try this out in my website’s redesign that I am working on

  • Amber Rake

    yeah demo not working properly

  • ziobudda

    under chrome osx the demo does not work.

    • http://twitter.com/antoniopratas Antonio Pratas

      What’s the version of your browser? And make sure your javascript is on, otherwise it won’t work.

  • http://twitter.com/joramoudenaarde Joram Oudenaarde

    I’ve been looking around for such an example… thanks for sharing! :)

  • http://twitter.com/e11world Eddie11

    It is resizing for me on Chrome, IE8, FFox on Win7. Very neat. I saw this on a site 3 weeks ago and now I can do it too!!

  • http://www.facebook.com/AllanStepps Allan Stepps

    Just be more efficient… No need the “large” class (just say it’s the default one). And the effect in one line of jQuery:

    $(document).on(“scroll”,function(){
    $(“header”).toggleClass(“small”, $(document).scrollTop()>100);
    });

    Enjoy =)