LearnHow to Build a “Three Line” Drop-down Menu for a Responsive Website in jQuery

Andrew Chalkley
writes on October 30, 2012

Share with your friends










Submit

Our goal is to build a “three line” or “3 line” (☰) menu for a responsive website. We want to do this without adding additional markup to the page. Any additional markup we want to include must be added dynamically. We’re going to use jQuery to help us out.

Initial State

So here is our, initial state.

<!DOCTYPE html>
<html>
<head>
	<title>Responsive 3-Line Menu</title>
	<style type="text/css">
	* {
		margin: 0;
		padding: 0;
	}
	ul {
		width:100%;
	}

	li {
		width:33%;
		float:left;
		border-right: 1px solid #eee;
	}
	li:last-child {
		border-right:none;
	}

	li a {
		display: block;
		width:80%;
		background:#ddd;
		padding:4% 10%;
		font-size:1.35em;
		text-decoration: none;
	}

	@media screen and (max-width: 768px) {
		#menu {
			width:1.4em;
			display: block;
			background:#ddd;
			font-size:1.35em;
			text-align: center;
		}
		#nav.js {
			display: none;
		}
		ul {
			width:100%;
			list-style:none;
		}
		li {
			width:100%;
			border-right:none;
		}
	}

	@media screen and (min-width: 768px) {
		#menu {
			display: none;
		}
	}
	</style>
</head>
<body>
<ul id="nav">
	<li><a href="#">Home</a></li>
	<li><a href="#">About</a></li>
	<li><a href="#">Contact</a></li>
</ul>
</body>
</html>

We have a navigation unordered list with the id of nav. Each menu item is floated left when the browser’s viewport is larger than 768 pixels, any smaller they jump under each other.

Our aim is to hide them when we get to 768 and show a menu (☰). When you tap on the menu it reveals the navigation and once you tap again it hides it.

Getting Started

First we want to hide our navigation unordered list (#nav). In our CSS we’re doing display:none on our #nav.js. We can do this in jQuery in the following way.

$("#nav").addClass("js");

So if JavaScript is enabled it now hides. When we shrink our viewport.

Next we want to add the menu link before our #nav.

$("#nav").addClass("js").before('<div id="menu">☰</div>');

Because we have the CSS already set up to show and hide the ☰ menu we don’t have to do anything here. Next we need to add a click listener to the menu and then toggle the visibility of the #nav element.

$("#menu").click(function(){
	$("#nav").toggle();
});

Finally, if you show and hide the navigation in a small viewport and then expand the viewport again the navigation is always hidden. This is because the toggle method adds a style attribute to the navigation element. To fix this we by removing the style attribute using the removeAttr method. We need to call this when the window resizes and the width is greater than 768 pixels.

$(window).resize(function(){
	if(window.innerWidth > 768) {
		$("#nav").removeAttr("style");
	}
});

And that’s it. In a relatively short amount of code you’ve progressively enhanced a responsive site to have a “three line” menu.

Update: The code can be found on GitHub here.

31 Responses to “How to Build a “Three Line” Drop-down Menu for a Responsive Website in jQuery”

  1. How to dowload full example ? Who do can share ? Mail: nhannn@bkc.vn

  2. any clever way to have this thing animate?

  3. M. McKendry on March 31, 2013 at 1:49 pm said:

    Can you put up an example to download?

  4. MichMcK on April 11, 2013 at 12:56 pm said:

    Could you make a full example WITH the jQuery so that I can copy and paste it? I’m getting the nav but it’s not collapsing. Thanks!!

  5. Me me me! on May 1, 2013 at 7:58 am said:

    I agree Aweosme 😀 Definitely will use this!

  6. Richard Martin on May 2, 2013 at 8:06 am said:

    @chalkers:disqus

    I was testing your demo and I love it, its so simple its unreal.

    I have noticed a bug however it probably is not going to affect anyone because you don’t often resize the viewport

    reproduce:
    1) scale browser window from desktop size to < 768px

    2) open navigation or search
    3) scale window back to desktop size

    the menu icons appear out of line and the search icon does not return to original size.

    Otherwise a perfect solution!
    Thanks.

    Rich.

  7. magic on May 5, 2013 at 5:23 am said:

    how to add an animation to the movement?

  8. Harjeet Singh on May 7, 2013 at 4:27 pm said:

    Please add the link to demo of the menu.
    Team S plus H

  9. chris on May 13, 2013 at 7:41 pm said:

    thnaks for this tutorial

  10. MichMcK on May 16, 2013 at 6:49 pm said:

    PA-LEEEEEZE put a downloadable example of this html, CSS and jQuery. I’m having trouble understanding where/how to do the script.

    Thanks

  11. tabby on May 20, 2013 at 3:18 pm said:

    would love to see the full code, don’t know enough about implementing jquery to get this to work :/

  12. Gareth on June 1, 2013 at 9:06 am said:

    Can someone tell me what I’m doing wrong here?

    $(“#nav”).addClass(“js”).before(‘☰’);

    $(“#menu”).click(function(){
    $(“#nav”).toggle();
    });

    $(window).resize(function(){
    if(window.innerWidth > 768) {
    $(“#nav”).removeAttr(“style”);
    }
    });

    Responsive 3-Line Menu

    * {
    margin: 0;
    padding: 0;
    }

    ul {
    width:100%;
    }

    li {
    width:33%;
    float:left;
    border-right: 1px solid #eee;
    list-style: none;
    }

    li:last-child {
    border-right:none;
    }

    li a {
    display: block;
    width:80%;
    background:#ddd;
    padding:4% 10%;
    font-size:1.35em;
    text-decoration: none;
    }

    @media screen and (max-width: 768px) {
    #menu {
    width:1.4em;
    display: block;
    background:#ddd;
    font-size:1.35em;
    text-align: center;
    }

    #nav.js {
    display: none;
    }

    ul {
    width:100%;
    list-style:none;
    }

    li {
    width:100%;
    border-right:none;
    }
    }

    @media screen and (min-width: 768px) {
    #menu {
    display: none;
    }
    }

    Home
    About
    Contact

  13. Concerned on June 13, 2013 at 4:16 pm said:

    As a professional, I would respectfully ask that this article be rewritten as the author not only references code that is not there, claims that the code has been updated with “it’s there now”, and also provides no download of the source files. These things together provide a less than stellar user experience for people who might be trying to learn something and rather walk away more confused by the obfuscation of this article.

    Thanks.

  14. Can anyone tell me how I can replace the .before(‘☰’) so I can have my own image through a css class? Thanks

  15. Really nice write up, easy to follow and well explained so had the menu up and running in no time. I’m new to jquery so this really helped explain a few things, thanks.

  16. I can not seem to get this 3 line nav to work with my other media queries. Once implemented, when I scroll inward to 768px the box shows up with the links as if the box was already clicked. Any suggestions?

    P.S. It won’t show my 480 and 320 media queries either. It acts like it is stuck on the 768 media query.

  17. opera mini hater on August 26, 2013 at 2:53 pm said:

    this wont work in opera

  18. nice and easy.

  19. If I have a one page website with anchor links and I tap one of the links, the menu doesn’t go away on click. Is there anything else I need to add?

    $(“#nav”).addClass(“js”).before(‘☰’);

    $(“#menu”).click(function(){

    $(“#nav”).toggle();

    $(“#nav”).toggleClass(“dropdown”);

    });

  20. If I have a one page website with anchor links and I tap one of the links, the menu doesn’t go away on click. Is there anything else I need to add?

    $(“#nav”).addClass(“js”).before(‘☰’);

    $(“#menu”).click(function(){

    $(“#nav”).toggle();

    $(“#nav”).toggleClass(“dropdown”);

    });

  21. Simply Awesome Thanks a lot

  22. I was testing your demo and I love it, its so simple its unreal.

Leave a Reply

Learn to code with Treehouse

Start your 14 day free trial today and get access to hundreds of video courses in web development, design and business!

Learn more