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

3linemain

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.

Free Workshops

Watch one of our expert, full-length teaching videos. Choose from either HTML, CSS or Wordpress.

Start learning

Andrew Chalkley

I'm an alien, I'm a legal alien, I'm an Englishman in Portland. All of my professional life I've worked with computers online. I'm a polyglot programmer and like using the right tools for the job. In my spare time I enjoy spending time with my young family and when I get chance, sticking opponents in Halo 4. You can find me in most places @chalkers.

Comments

30 comments on “How to Build a “Three Line” Drop-down Menu for a Responsive Website in jQuery

  1. 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!!

  2. @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.

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

    Thanks

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

  5. 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

    • Need to wait till the dom it’s ready
      $(function() {
      // your stuff here
      });

  6. 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.

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

  8. 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.

  9. 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.

  10. 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”);

    });

  11. 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”);

    });