Skip to main content

Responsive and mobile friendly menus are a must in web design nowadays. This tutorial will take you through exactly how to create one.

The other day I received an email from Sviatoslav about another post, he asked me…

I have a problem with this bar: you cannot simply change the { position } of the nav element to fixed (so it will always appear on the top, like your red top navigation bar).

That got me thinking. Not only was it time to rewrite my most popular tutorial, but it was time to pump it full of steroids to become a kick-ass navigation menu.

Thinking about what a navigation menu should be I decided on the following criteria:

  • Mobile first
  • Responsive
  • Clean & simple design
  • Mobile drop-down menu
  • Fast loading

With that in mind I got to work, and this is what I came up with.

See the Pen Mobile Friendly HTML 5 and CSS 3 Responsive Fixed Navigation Menu by lawnch (@lawnch) on CodePen.

Mobile First vs. Responsive CSS Design

Before I delve into the code I want to cover one of the core concepts for this navigation menu. You may see people talking about “Mobile First” as if it’s an important thing. For a long time I thought that was the same as building a responsive design. Wrong!

Responsive Web Design

A responsive design responds to changing viewport sizes and is optimised for different devices. All websites should now be moving to a responsive design, if not they should have a dedicated mobile website. Heck, this has been around for 3 years now.

What is Mobile First?

Mobile first isn’t just the next step, but it’s the first step. You shouldn’t begin by creating your full site design, start small and scale up. Yes, build your mobile CSS first, then tailor it for desktop. By doing this you’ll deal with the intricate mobile platform first, making it easier to scale. If you think about how difficult it is to cram a sleeping bag back into the tiny bag, that’s what starting with desktop is doing.

Creating a Mobile First Design

What mobile first really means is content first, that’s a great concept. Adding all the flashy features of yesteryear –no pun intended, is a thing of the past. Build the site around the content and add the bells and whistles for larger screens later.

The days of a designer hopping onto Photoshop to whip up the whole design then passing it to a coder are now long gone. You need to get into coding around the content and apply the design practices along the way. By all means, plan your content with wireframes and decide on a theme, but don’t design every page and try to scale down for mobile.

Regardless of whether you choose to follow the mobile first design principle, the first piece of code you should add between your <head> tags is to set the initial scale. Not only does this set the president for your mobile site, but it ensures your design is shown purely as you intended.

[html]<meta name="viewport" content="initial-scale=1">[/html]

Building the Navigation Menu HTML

There’s a variety of different software out there that’s looking to browse your website – web browsers, screen readers, and bots. The easier we make it for them to do it the better your site ranking will be. HTML 5 makes this very easy. We no longer need to use <div> to house everything, instead we should use <header> and <nav>. This explicitly shows exactly what we’re creating in the code. The best thing is that we can treat them exactly the same as our typical <div> element.

[html]
<header>
<nav>
<!–Code Here–>
</nav>
</header>

[/html]

This is a very simple example of HTML 5 that we can now move forwards with.

Navigation Menu Structure

A very common mistake with navigation menu’s is how they’re structured. Search engines do take speed into consideration when building their rankings. A poorly structured navigation menu won’t just slow down one page, but it’ll impact your whole site. So listen up.

A navigation menu is a list of links to different pages on your website. The keyword there being list. Many websites still present this in a table format. This isn’t only wrong, but it’s much slower loading.

For our navigation menu we’re going to use an unordered list by using the <ul> element. This will give us the correct page structure and will load nice an fast.

[html]
<header>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Forum</a></li>
<li><a href="#">Help</a></li>
</ul>
</nav>
</header>

[/html]

So far so good.

Creating the Drop Down Menu

Next we want to take the concept we’ve used to create the primary navigation menu, then use it to create a sub menu that will be given a drop down ability within CSS.

A drop down menu is simply a nested listed within another list. This means taking what we’ve done before and re-applying it inside the first menu. We need to wrap our sub menu within another <nav> element, then add a second un-ordered list <ul>.

Once that’s done you’ll end up with this –

[html]
<header>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li>
<a href="#">Blog</a>
<nav>
<ul>
<li><a href="#">Articles</a></li>
<li><a href="#">Tutorials</a></li>
<li><a href="#">Humour</a></li>
<li><a href="#">Gaming</a></li>
<li><a href="#">Music</a></li>
</ul>
</nav>
</li>
<li><a href="#">Forum</a></li>
<li><a href="#">Help</a></li>
</ul>
</nav>
</header>

[/html]

Adding A Logo to the Navigation

As the navigation menu is typically at the top of every page we want to add a logo to it so users know where they are. Unfortunately there isn’t a <logo> element just yet, so we need to create a <div>.

[html]
<header>
<div id="logo" class="menuUp">
<h1>Adam Bray.</h1>
<div id="navToggle"><a href="#">Menu</a></div>
</div>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li>
<a href="#">Blog <span class="toggle">Expand</span><span class="caret"></span></a>
<nav>
<ul>
<li><a href="#">Articles</a></li>
<li><a href="#">Tutorials</a></li>
<li><a href="#">Humour</a></li>
<li><a href="#">Gaming</a></li>
<li><a href="#">Music</a></li>
</ul>
</nav>
</li>
<li><a href="#">Forum</a></li>
<li><a href="#">Help</a></li>
</ul>
</nav>
</header>

[/html]

You may have noticed a few extra bits of code in there. This is what’s been added.

[html]
<div id="logo" class="menuUp">
[/html]

Firstly you can see I’ve used both an id and a class this will give us a base style and a switchable style when using jQuery to toggle the mobile navigation menu.

[html]
<div id="navToggle"><a href="#">Menu</a></div>

[/html]

Secondly, I’ve added a menu link. This will be used to toggle the menu on mobile devices. You can replace the text with an image if you wish.

[html]<a href="#">Blog <span class="toggle">Expand</span><span class="caret"></span></a>[/html]

The final change is the expand icon and a caret (arrow) to our expandable menu item. This will change depending on the screen size and will let the user know they have more options to view.

Mobile First CSS Navigation Menu

This is where we get down to the core concept for the menu. First I’m going to show you how to create the mobile view, then we’ll scale it up using CSS media queries for desktop and tablet users for our responsive navigation menu.

Getting Started with any CSS Project

You should start any CSS project by resetting all browsers to the same level/expectation. Secondly you want to set your core styles, usually done by styling the <body> element. If you’re adding this to your pre-existing website then you may wish to take this out of the code.

[css]* {
margin: 0;
padding: 0;
outline: none;
box-sizing: border-box;
}

body {
background: #eee;
color: #444;
-webkit-font-smoothing: antialiased;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
font-weight: 400;
height: auto !important;
height: 100%;
min-height: 100%;
text-rendering: optimizeLegibility;
}[/css]

Now we start by creating our mobile first header. It’s best to start with the larger building blocks at the top of your CSS then work down. Remember, these styles are currently for the mobile site, our desktop/tablet version will be added later on.

[css]header {
background-color: rgb(140, 193, 193);
border-bottom: 1px solid rgba(0,0,0,.15);
display: flex;
flex-direction: column;
text-align: center;
}[/css]

Within this code I’ve used rgb() and rgba() colours. This is mainly down to personal preference with rgb(), but using rgba() allows us to set an “alpha” value, which makes it transparent.

How does a Flexbox Container work?

I’ve decided to use a flexbox model for our container element. This gives us a lot of power when it comes to making a mobile first website.

  • display: flex: This defines the flex container, enabling a flex context for it’s direct children.
  • flex-direction: column: We can either use row or column – along with reversing either. Because we’re mobile first we want to use column so all child elements are full width, vertical elements.

By using flex-direction you can hopefully see how we’re going to evolve the navigation menu for larger screens later on. We’ll be able to shift the direction of our content on the defined flexbox axis.

Styling the Navigation Menu with CSS

The <nav> element will be used to hold our navigation menu list. This is where the majority of the action will be happening, so we need to ensure it’s robust.

[css]header > nav {
background-color: white;
display: none;
flex: 1;
transform: 300ms all ease;
}

header nav > ul {
list-style-type: none;
}

header nav > ul > li {
border-bottom: 1px dotted rgba(0,0,0,.1);
position: relative;
}

header nav > ul > li > a {
display: block;
color: rgba(0,0,0,.65);
font-weight: 700;
padding: 1.5rem 0;
text-decoration: none;
transition: 250ms all ease;
}[/css]

I’ve set the <nav> to flex: 1. This means it will take up all the space it can. It works differently to display: block in the way block elements push everything out the way, flex: 1 will only grow into the space it’s given. In this case there’s nothing else in the way so it’ll go to 100% width.

It’s important to note the use of position: relative for the <li> element. This will allow us to position child elements relative to the parent. Simply put, it means we can easily position the drop down menu exactly below the link you need.

With our basic menu out covered we can start getting fancy. We need to add indicators of dropdown menus, along with tidying up the list styles.

[css]header nav > ul > li:last-of-type {
border-bottom: none;
}

header nav > ul > li > a span.toggle {
background-color: rgba(0,0,0,.05);
border-radius: 3rem;
color: rgba(0,0,0,.25);
font-size: 0.75em;
font-weight: 500;
padding: 2px 8px;
text-transform: lowercase;
}

header nav > ul > li > a span.caret {
display: none;
}

header > nav > ul > li:hover > a {
color: rgb(140, 193, 193);
}[/css]

The first style is for the :last-of-type list item element. What this means is the last link in our navigation menu has a certain style. In this case we’re removing the bottom border. A colon followed by a statement like that is a CSS selector, with CSS 3 recently adding a lot more, giving us greater control.

The next 3 styles are responsible for giving the user a visual indicator that there’s a drop down menu. .toggle is responsible for showing a grey indicator next to the navigation item, either saying expand or close. .caret is the arrow used for desktop users, but we want to hide that on mobile so it’s display: none.

Finally we’ve set a hover style for the list items to change the colour if users are browsing on a small screen with a mouse.

Creating the CSS Drop Down Menu

The key features of a drop down are that it’s hidden until you need it, and it’s positioned where you expect it.

I’ve already mentioned how using position: relative will allow us to to put the drop down menu where we need it. Now we can put that to use.

[css]header > nav > ul > li > nav {
background-color: rgb(51,51,51);
border-radius: 1.5em;
box-shadow: 0 2px 8px rgba(0,0,0,.6);
display: none;
overflow: hidden;
position: absolute;
right: 5%;
width: 90%;
z-index: 100;
}[/css]

Have a look below to understand how the drop down menu CSS works.

  • background-color: rgb(51,51,51) Change the rgb() value here to edit the background colour of the drop down menu
  • border-radius: 1.5em A border radius is the amount of rounded corners to apply to the menu
  • box-shadow: 0 2px 8px rgba(0,0,0,.6) Modify the settings of the box’s drop shadow [h-shadow v-shadow blur color]
  • display: none Hide the box until it’s needed – don’t modify
  • overflow: hidden Works with the border-radius to stop content appearing outside the box
  • position: absolute Place the drop down menu directly below the main link – don’t modify
  • right: 5% Pull the drop down menu 5% from the right of the screen
  • width: 90% The width of the drop down menu is 90%
  • z-index: 100 Place the drop down menu above everything else – unless other items have a higher z-index

Next we need to style the drop down menu’s list items, or the sub-navigation.

[css]header > nav > ul > li > nav > ul > li > a {
color: rgba(255,255,255,.85);
transition: 300ms all ease;
}

header > nav > ul > li > nav > ul > li:hover > a {
background-color: rgba(0,0,0,.6);
color: rgba(255,255,255,1);
}[/css]

Using position: absolute and combining it with right: 5% and z-index: 100 we can place the sub-navigation menu directly underneath the parent link. Setting a box-radius will give us a nice rounded corner effect, and a box-shadow will add a dark shadow over the content below. You can increase the size of this by increasing the 8px blur.

Adding a Logo and Toggle Button to the Navigation Bar

The final part of the navigation is the logo area. Within it we also have the navigation menu toggle for the main menu on mobile. The toggle will work with jQuery, but that comes later.

[css]header > div#logo {
line-height: 70px;
position: relative;
}

header > div#logo > h1 {
color: white;
font-weight: 300;
text-transform: lowercase;
}[/css]

Firstly we need to create the logo container. This will house our menu toggle and overall site logo. Similar to the navigation, we want to use position: relative so that we can place the toggle div exactly where we want.

The <h1> style is to create the logo. This isn’t important for the menu, so you can replace it with your own logo, image or text. For SEO purposes it’s important to include a <h1> element on your page as it denotes what the page is about.

Next for the menu toggle button. Users will click this and the main navigation menu will drop down when browsing on a mobile device.

[css]header > div#logo > div#navToggle {
background-color: rgba(0,0,0,.15);
position: absolute;
right: 0;
top: 0;
transition: 300ms all ease;
}

header > div#logo > div#navToggle:hover {
background-color: rgba(0,0,0,.1);
}

header > div#logo > div#navToggle > a {
color: rgba(255,255,255,.85);
display: block;
font-size: 0.85em;
font-weight: 600;
padding: 0 2.5rem;
text-decoration: none;
transition: 300ms all ease;
}

header > div#logo > div#navToggle:hover > a {
color: rgba(255,255,255,1);
}[/css]

There are two larger blocks of code here. This is what it all means.

header > div#logo > div#navToggle – The core toggle button container
  • background-color: rgba(0,0,0,.15) Set a very subtle black background with 15% opacity
  • position: absolute Position the button along the X and Y axis
  • right: 0 Position the button on the right of the screen
  • top: 0 Position the button on the top of the screen
  • transition: 300ms all ease If other styles are triggered for this element then transition over 0.3 seconds (CSS animation)
header > div#logo > div#navToggle > a – The link inside the button container
  • color: rgba(255,255,255,.85) Set the font colour as white, but only 85% opacity
  • display: block Allow for padding within the element
  • font-size: 0.85em The text should only be 85% of the normal font size
  • font-weight: 600 Make the font semi-bold
  • padding: 0 2.5rem Add 0 padding to the top and bottom, add 2.5rem padding to the left and right
  • text-decoration: none Remove the underline on the link
  • transition: 300ms all ease If other styles are triggered for this element then transition over 0.3 seconds (CSS animation)

How to Make the HTML Navigation Menu Responsive with CSS

Using CSS Media Queries we’re able to take the standard navigation menu and changes the CSS based on the size of the user’s screen. This is where mobile first comes in again. We’ve already created the mobile site, so now we need to create a media query for if the screen is larger than expected. We do that like so –

[css]/* Medium screens */
@media all and (min-width: 600px) {
/*Code goes here*/
}[/css]

Depending on the size of screens you want to class as mobile devices, you can change the 600px to less or more.

Now we can start creating the new styles. All we simply do now is create a second set of styles that will overwrite our original values. This doesn’t mean the previous styles won’t be applied, these new ones will just go over the top. That means if something doesn’t need changing then we don’t have to rewrite it.

Changing the Menu Style from Mobile to Screen

Now we need to consider how to change the menu from mobile centric to screen/desktop based. Mobile users need large buttons to press with fingers; desktop/screen users have a mouse. This means the navigation menu can be more intricate for larger screens than mobile.

We can start by hiding our toggle navigation button, the expand/close icon, and adding a style to the caret.

[css]header > div#logo > div#navToggle {
display: none;
}

header nav > ul > li > a span.toggle {
display: none;
}

header nav > ul > li > a span.caret {
border-bottom: 4px solid transparent;
border-top: 4px solid rgba(0,0,0,.65);
border-right: 4px solid transparent;
border-left: 4px solid transparent;
border-radius: 1px;
content: "";
display: inline-block;
height: 0;
margin: 0 0 0 .25rem;
transition: 250ms all ease;
width: 0;
vertical-align: middle;
}

header nav > ul > li:hover > a span.caret {
border-top-color: rgb(140, 193, 193);
transform: rotate(270deg);
}[/css]

The big change here is the caret. Here’s how that works.

  • border-bottom: 4px solid transparent Set the bottom border to 4px without a colour
  • border-top: 4px solid rgba(0,0,0,.65) Set the top border to 4px with the same colour as the text
  • border-right: 4px solid transparent Set the right border to 4px without a colour
  • border-left: 4px solid transparent Set the left border to 4px without a colour
  • border-radius: 1px Add a very small rounding to the borders
  • content: "" Add some blank content to the span
  • display: inline-block display block, but don’t push other elements down
  • height: 0 No height
  • margin: 0 0 0 .25rem Add a small margin to the left
  • transition: 250ms all ease If anything changes then animate it over 0.25 seconds
  • width: 0 No width
  • vertical-align: middle Align in the middle of the line

With the :hover style we’ve added a transform style. This will spin the element 270 degrees when the user hovers over it.

Creating the HTML Drop Down Menu

Now the base styles for the header are out of the way, we can focus on styling the navigation menu itself, along with making our drop down menu.

[css]header > nav {
background-color: transparent;
display: block;
}

header > nav > ul {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
}

header nav > ul > li {
border-bottom: none;
}

header nav > ul > li > a {
padding: 0 1.25rem;
}[/css]

Not too many changes there, but the main one is for the <ul> container. We need to take the columns we’ve used in mobile, and convert it into a row for our desktop menu.

  • display: flex Set the president for flexbox
  • flex-flow: row wrap If the box isn’t big enough then wrap the child elements
  • justify-content: flex-end Populate from right to left

Finally we need to make the drop down menu active. This is done by using :hover and setting the display value from none to block.

[css]header > nav > ul > li:hover > nav {
background-color: rgb(51,51,51);
border-radius: .25em;
box-shadow: 0 2px 8px rgba(0,0,0,.6);
display: block;
line-height: 3em;
right: -50%;
width: 196px;
}[/css]

This style is applied to the <nav> element that’s contained within a <li> when the <nav> is hovered over by a mouse.

That concludes the CSS part of this tutorial. I’ve taken you through creating a mobile ready HTML navigation menu that uses responsive CSS media queries to scale up for desktop users. The drop down menu now works flawlessly when the user’s have a mouse to trigger it, but we currently don’t have a solution for mobile users. Enter jQuery.

How to Make a Mobile Drop Down Menu with jQuery

So far we’ve created the HTML and CSS for our navigation menu. Now we need to use jQuery (a Javascript library) to give mobile users the same functionality.

Before we start coding our jQuery functions, we need to include the jQuery library on the site. To do this we’ll use the Cloudflare CDN (content delivery network) to speed up the delivery of the library. Include this between your <head> tags.

[html]
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"
[/html]

First we start by wrapping our jQuery functions in a function that stops the functions running until the document is loaded/ready. If we don’t do this then you’ll start seeing errors as the script will be looking for DOM elements that don’t yet exist on the page because it hasn’t loaded them yet.

[js]$(document).ready(function() {
//Functions go here
});[/js]

Creating the show/hide function with jQuery Toggle

jQuery comes with a load of different toggle functions built in. This means we have fantastic functionality that we can use very easily. To toggle the main navigation menu for mobile users we do –

[js]$("#navToggle a").click(function(e){
e.preventDefault();

$("header > nav").slideToggle();
$("#logo").toggleClass("menuUp menuDown");
});[/js]

If you’re learning jQuery then let me explain that for you.

  • When the link inside the element with id="navToggle" is clicked
  • Set the event as the variable “e”
  • Prevent “e” from doing what it’s meant to – in this case following the href link
  • Find the <nav> directly inside the <header>
  • Slide it up or down depending on its current state – toggle it
  • Find the element with id=”logo”
  • Toggle it between the two classes menuUp and menuDown -this adds a drop shadow to the element (see CSS)

I hope now that has made the functionality nice and clear. It’s a basic function that runs at the core of our navigation menu for mobile users.

Creating the Drop Down Menu for Mobile Devices

Next we need to create the drop down menu functionality. Again, this is a very small function, but it uses different functionality within jQuery than the last function.

[js]
$("header > nav > ul > li > a").click(function(e) {
if($( window ).width() <= "600") { if($(this).siblings().size() > 0 ) {
e.preventDefault();
$(this).siblings().slideToggle("fast")
$(this).children(".toggle").html($(this).children(".toggle").html() == ‘close’ ? ‘expand’ : ‘close’);
}
}
});[/js]

Let me explain this one for you.

  • When a tier 1 link is clicked
  • Set the event as the variable “e”
  • If the window is less than 600px wide – i.e. a mobile device
  • If it has siblings – a sibling is another element within the parent element (see below)
  • Prevent “e” from doing what it’s meant to – in this case following the href link
  • slideToggle the siblings – the sub navigation in this case
  • Get the toggle icon, find out whether it says expand or close, switch it to the other one

The function itself isn’t too complicated, just a couple of complex lines to understand.

What are jQuery Siblings?

A sibling is another element owned by the same parent element. Such as this –

[html]
<ul>
<li>Element 1</li>
<li>Element 2</li>
</ul>

[/html]

In this example Element 1 and Element 2 are siblings.

Tidying up the Navigation Menu

Finally we need to create a tidy up function for if the user decides to play with the screen size between what we’re classing as mobile and desktop.

[js]$(window).resize(function() {
if($( window ).width() >= "600") {
$("header > nav").css("display", "block");

if($("#logo").attr(‘class’) == "menuDown") {
$("#logo").toggleClass("menuUp menuDown");
}
}
else {
$("header > nav").css("display", "none");
}
});[/js]

This function is simpler than the last, but let me walk you through it.

  • When the window is resized
  • If the window width is equal to or greater than 600px
  • Set the navigation to display: block instead of display: flex
  • If the class of the element with the id="logo" is "menuDown" then change it to "menuUp"
  • If the width is a mobile width then hide the <nav> element

And that’s the jQuery code done.

Conclusion

In this tutorial I’ve taken you through how to create a HTML 5 navigation menu. I’ve shown you how to use CSS 3 to create a mobile first design that’s responsive for desktop users, putting content first. I’ve then taken you through using jQuery to add mobile functionality to the navigation menu so the drop down menu works across all devices.

Please leave your comments below. I love seeing and hearing about how you guys are using it, and answering any questions you may have.

Full Code for the Drop Down Navigation Menu

HTML

[html]
<header>
<div id="logo" class="menuUp">
<h1>Adam Bray.</h1>
<div id="navToggle"><a href="#">Menu</a></div>
</div>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li>
<a href="#">Blog <span class="toggle">Expand</span><span class="caret"></span></a>
<nav>
<ul>
<li><a href="#">Articles</a></li>
<li><a href="#">Tutorials</a></li>
<li><a href="#">Humour</a></li>
<li><a href="#">Gaming</a></li>
<li><a href="#">Music</a></li>
</ul>
</nav>
</li>
<li><a href="#">Forum</a></li>
<li><a href="#">Help</a></li>
</ul>
</nav>
</header>

[/html]

CSS

[css]* {
margin: 0;
padding: 0;
outline: none;
box-sizing: border-box;
}

body {
background: #eee;
color: #444;
-webkit-font-smoothing: antialiased;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
font-weight: 400;
height: auto !important;
height: 100%;
min-height: 100%;
text-rendering: optimizeLegibility;
}

header {
background-color: rgb(140, 193, 193);
border-bottom: 1px solid rgba(0,0,0,.15);
display: flex;
flex-direction: column;
text-align: center;
}

header > div#logo {
line-height: 70px;
position: relative;
}

header > .menuDown {
box-shadow: 0 3px 5px rgba(0,0,0,.15);
}

header > .menuUp {
box-shadow: none;
}

header > div#logo > h1 {
color: white;
font-weight: 300;
text-transform: lowercase;
}

header > div#logo > div#navToggle {
background-color: rgba(0,0,0,.15);
position: absolute;
right: 0;
top: 0;
transition: 300ms all ease;
}

header > div#logo > div#navToggle:hover {
background-color: rgba(0,0,0,.1);
}

header > div#logo > div#navToggle > a {
color: rgba(255,255,255,.85);
display: block;
font-size: 0.85em;
font-weight: 600;
padding: 0 2.5rem;
text-decoration: none;
transition: 300ms all ease;
}

header > div#logo > div#navToggle:hover > a {
color: rgba(255,255,255,1);
}

header > nav {
background-color: white;
display: none;
flex: 1;
transform: 300ms all ease;
}

header nav > ul {
list-style-type: none;
}

header nav > ul > li {
border-bottom: 1px dotted rgba(0,0,0,.1);
position: relative;
}

header nav > ul > li:last-of-type {
border-bottom: none;
}

header nav > ul > li > a {
display: block;
color: rgba(0,0,0,.65);
font-weight: 700;
padding: 1.5rem 0;
text-decoration: none;
transition: 250ms all ease;
}

header nav > ul > li > a span.toggle {
background-color: rgba(0,0,0,.05);
border-radius: 3rem;
color: rgba(0,0,0,.25);
font-size: 0.75em;
font-weight: 500;
padding: 2px 8px;
text-transform: lowercase;
}

header nav > ul > li > a span.caret {
display: none;
}

header > nav > ul > li:hover > a {
color: rgb(140, 193, 193);
}

header > nav > ul > li > nav {
background-color: rgb(51,51,51);
border-radius: 1.5em;
box-shadow: 0 2px 8px rgba(0,0,0,.6);
display: none;
overflow: hidden;
position: absolute;
right: 5%;
width: 90%;
z-index: 100;
}

header > nav > ul > li > nav > ul > li > a {
color: rgba(255,255,255,.85);
transition: 300ms all ease;
}

header > nav > ul > li > nav > ul > li:hover > a {
background-color: rgba(0,0,0,.6);
color: rgba(255,255,255,1);
}

/* Medium screens */
@media all and (min-width: 600px) {
header > div#logo > div#navToggle {
display: none;
}

header {
background-color: white;
flex-direction: row;
line-height: 90px;
padding: 0 3rem;
position: fixed;
text-align: left;
width: 100%;
}

header > div#logo {
background-color: transparent;
line-height: 90px;
}

header > div#logo > h1 {
color: rgb(140, 193, 193);
}

header > nav {
background-color: transparent;
display: block;
}

header > nav > ul {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
}

header nav > ul > li {
border-bottom: none;
}

header nav > ul > li > a {
padding: 0 1.25rem;
}

header nav > ul > li > a span.toggle {
display: none;
}

header nav > ul > li > a span.caret {
border-bottom: 4px solid transparent;
border-top: 4px solid rgba(0,0,0,.65);
border-right: 4px solid transparent;
border-left: 4px solid transparent;
border-radius: 1px;
content: "";
display: inline-block;
height: 0;
margin: 0 0 0 .25rem;
transition: 250ms all ease;
width: 0;
vertical-align: middle;
}

header nav > ul > li:hover > a span.caret {
border-top-color: rgb(140, 193, 193);
transform: rotate(270deg);
}

header > nav > ul > li:hover > nav {
background-color: rgb(51,51,51);
border-radius: .25em;
box-shadow: 0 2px 8px rgba(0,0,0,.6);
display: block;
line-height: 3em;
right: -50%;
width: 196px;
}
}[/css]

jQuery / JavaScript

[js]$(document).ready(function() {
$("#navToggle a").click(function(e){
e.preventDefault();

$("header > nav").slideToggle();
$("#logo").toggleClass("menuUp menuDown");
});

$(window).resize(function() {
if($( window ).width() >= "600") {
$("header > nav").css("display", "block");

if($("#logo").attr(‘class’) == "menuDown") {
$("#logo").toggleClass("menuUp menuDown");
}
}
else {
$("header > nav").css("display", "none");
}
});

$("header > nav > ul > li > a").click(function(e) {
if($( window ).width() <= "600") { if($(this).siblings().size() > 0 ) {
e.preventDefault();
$(this).siblings().slideToggle("fast")
$(this).children(".toggle").html($(this).children(".toggle").html() == ‘close’ ? ‘expand’ : ‘close’);
}
}
});
});[/js]

Subscribe for Updates

Get notified about my latest content first and receive invitations for subscriber only competitions.

35 Comments

  • codenblog says:

    Hi Adam, Thank you for sharing this article it help a lot 🙂

  • Janet Ward says:

    Very interesting. There is one problem, the font colour is such a fine shade of elephant’s breath that is almost impossible to read.

  • html5 calendar says:

    I visited your website you have a good looking website and also I have read this article. I really like it. Lots of good information and found it very interesting and well done Keep it up

  • jing.wang says:

    header > nav {
    background-color: white;
    display: none;
    flex: 1;
    transform: 300ms all ease; // maybe is “transition: 300 ms all ease”;
    }

    header nav > ul > li > a {
    display: block;
    color: rgba(0,0,0,.65);
    font-weight: 700;
    padding: 1.5rem 0;
    text-decoration: none;
    transition: 250ms all ease;
    }

    great tutorail. awesome!!!!
    i m confused when i saw transition: 250ms all ease; transform: 300ms all ease; .
    is it mistake?
    if it is not mistake and pls tell me why?

  • jing.wang says:

    header > nav {
    background-color: white;
    display: none;
    flex: 1;
    transform: 300ms all ease; // maybe is “transition: 300 ms all ease”;
    }

    header nav > ul {
    list-style-type: none;
    }

    header nav > ul > li {
    border-bottom: 1px dotted rgba(0,0,0,.1);
    position: relative;
    }

    header nav > ul > li > a {
    display: block;
    color: rgba(0,0,0,.65);
    font-weight: 700;
    padding: 1.5rem 0;
    text-decoration: none;
    transition: 250ms all ease;
    }

    great tutorail. awesome!!!!
    i m confused when i saw transition: 250ms all ease; transform: 300ms all ease; .
    is it mistake?
    if it is not mistake and pls tell me why?

  • Olga Lefter says:

    Hi, Adam!

    Thank you for the tutorial!
    For a beginner, it was easy to follow and customize the code to my own design. The only problem I encountered is that I can’t succeed to give the contents of the header a max width, it spans on the entire length of the screen. I tried to add a container to the header but it seems to interfere with something and it breaks the header completely.

    Any thoughts on how to give the contents of the header a max width?
    Thank you!

  • ACP says:

    Your article is helpful. Nice work keep it up 🙂

  • Jason says:

    Hello Adam,

    I’m having an issue where the navbar covers content below. I’ve tried a multitude of solutions, but nothing fixes it. Can you take a look at this jsfiddle paste?
    https://jsfiddle.net/8qegavpL/

    Thanks,
    Jason

  • This article is wonderful. Thanks so much, it helped me a lot to put a great menu bar in my website.
    The only thing I could not correct is that on mobile only (Samsung S7 in my case), when the secondary menu expand and I loose a part of it below the bottom of the screen, I’m not able to drag it up without loosing it. Here is a page of my website if you want to try it.

    https://www.findnature.com/index-en.html

    Just expand the photos secondary menu.

    Thanks again!

  • Ian Haney says:

    Hi Adam. I am using this in a opencart website and on mobile view, the menu is expanded by default, is that right? if so could it not be expanded by default?

  • Andy Hughes says:

    Hi Adam,
    Great tutorial, well ready and pretty straight forward to follow along. Just a couple of silly little things. Your full code at the bottom of your page doesn’t show the > or < symbols properly and has converted them to character codes. For the copy and paste people, this will cause them some confusion. If you can change them to the correct symbols it would help.

    Also, your full css code has two classes which you don't make any reference to in the tutorial. I know they don't make any difference to function, just style, but it may be worth just mentioning this somewhere or including a reference to them. They are .menuUp and .menuDown.

    Other than that, it was a fantastic tutorial, particularly the explanations you gave for the code. Helped me understand the JS much better.

    Thanks
    Andy

  • Douglas Kamseu says:

    Is there a possibility to get the full code? im having issues making it completely work

  • Henrik Bossart says:

    Hey Adam, great tutorial!
    I only have one issue, whenever i go from the mobile to the desktop size, and have clicked the drop down in mobile, the dropdown in desktop doesn’t work.. any tips?

    Thanks in advance

  • M.J. says:

    Wow … I had been struggling with some of these very issues. You helped me realize that jQuery really was the only elegant way to approach the mobile drop-down interface. Also, the “flexbox” paradigm cleared up much that was obscured. Many thanks, Adam !!!

  • Rusty says:

    I couldn’t get the menu to expand below the top level. I switched the jQuery line 23 from:

    if($( window ).width() 0 ) {
    to:
    if($( window ).width() <= "600") { if($(this).children() ) {

    …because I figured that the expansion condition of having siblings is invalid: it should be having children. It works for me anyway.

    Having said that, this was an awesome help in getting my site mobile-ready. Thanks!

    • Nogard says:

      JQuery isn’t best choice for doing responsive navbar, you should use Javascript, it s much much easier.

      • Adam says:

        It depends on your preference. If you’re already using jQuery on your site then there’s nothing wrong with expanding on that. I’m not a fan of using libraries such as jQuery for small functionality.

  • Hnas says:

    I am having this trouble:

    ready.js:24 Uncaught TypeError: $(...).siblings(...).size is not a function
        at HTMLAnchorElement.<anonymous> (ready.js:24)
        at HTMLAnchorElement.dispatch (jquery.min.js:3)
        at HTMLAnchorElement.q.handle (jquery.min.js:3)
    

    The piece of js:

    $(“header > nav > ul > li > a”).click(function(e) {
    if($( window ).width() 0 ) { <—— IT POINTS HERE THE ERROR
    $(this).siblings().slideToggle("fast")
    $(this).children(".toggle").html($(this).children(".toggle").html() == 'close' ? 'expand' : 'close');
    }
    }
    });

    Can you help? the site is ptc.megaclique.com if you desire to see the source.

  • Mike Konshak says:

    I am trying to make a 17 year old HTML website using FRAMES to be more mobile friendly. See: sliderulemuseum.com My biggest challenge is trying to understand CSS and HTML 5 and to come up with a new menu system to eliminate the menu Frame. I’m 70 and this is a grueling task for me. This is a non-profit enterprise so there are very little funds to hire programmers. I created the domain sliderulemuseum.org to experiment with different menu designs without accidentally stomping on the flagship site. I want a top fixed menu that has dropdown and does not scroll out of the way. The museum website is image intensive, over 7000 images, that get displayed in long galleries, using tables. Can you help me with a design that I can understand and alter without crashing the whole thing? I don’t know what to do with you jquery/javascript code.

    • Adam says:

      You’re not kidding when you say the site is old! I would personally look at using a CSS framework to simplify your development cycle. The use of tables and frames is very outdated and will be negatively impacting your search engine rankings.

      Start by thinking about the critical links you need to display and treating them as the primary navigation. Displaying 30 galleries in your navigation looks like a lack of focus to me.

      Ps. Sorry this has only just been approved, it was flagged as spam.

  • Filip says:

    How would i align the items (like Home, About, Blog, …) to the bottom ?
    I tried using vertical-align: bottom; and fiddled with inlines in many places but it doesn’t work,
    whatever I do.
    Any help?

  • Mika Kaakinen says:

    Should tag include the navigation or should they be kept seperate?

  • Mika Kaakinen says:

    You know a lot about web development Adam and the tutorial is excellent giving much information. My only complain is the same as Dennis: your selectors are long. Using classes to shorten them might not be a bad idea. That way the code would be readable. Thank you for your work and instruction!

  • Ella says:

    Hi Adam,

    Is the latest version of this available for download as files anywhere?
    I’m having some issues getting this to work as intended. Many thanks x

  • Robert says:

    Nice tutorial. For those copying and pasting the code above, note that javascript has 3 errors – the greater than and less than signs have been converted to html entities which of course won’t copy over. < stands for the less-than sign ( ). Both need to be corrected in order to implement.

  • Iven says:

    Hi Adam,
    why you do “height: auto !important;” and “height: 100%;” at the body tag?

    Great tutorial!

    Thank you!
    Iven

  • Dennis says:

    I am new to web development. So please forgive me if this is a dumb question.

    To me, it seems that you have written your css selector out to be very long.

    “header nav > ul > nav > ul > li > a”

    Is there a way to shorten this?

  • Leslie Støvring says:

    Thanks for this great turtial – just what i was looking for.

    But i cannot get it to work in IE 10 or at mobil devices …. could you help me out as i do not think it is missing a lot 🙂

    Page: walterstov.dk/leslie

    thanks in advance
    \L

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.