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 menuborder-radius: 1.5em
A border radius is the amount of rounded corners to apply to the menubox-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 modifyoverflow: hidden
Works with the border-radius to stop content appearing outside the boxposition: absolute
Place the drop down menu directly below the main link – don’t modifyright: 5%
Pull the drop down menu 5% from the right of the screenwidth: 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 higherz-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% opacityposition: absolute
Position the button along the X and Y axisright: 0
Position the button on the right of the screentop: 0
Position the button on the top of the screentransition: 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% opacitydisplay: block
Allow for padding within the elementfont-size: 0.85em
The text should only be 85% of the normal font sizefont-weight: 600
Make the font semi-boldpadding: 0 2.5rem
Add 0 padding to the top and bottom, add 2.5rem padding to the left and righttext-decoration: none
Remove the underline on the linktransition: 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 colourborder-top: 4px solid rgba(0,0,0,.65)
Set the top border to 4px with the same colour as the textborder-right: 4px solid transparent
Set the right border to 4px without a colourborder-left: 4px solid transparent
Set the left border to 4px without a colourborder-radius: 1px
Add a very small rounding to the borderscontent: ""
Add some blank content to the spandisplay: inline-block
display block, but don’t push other elements downheight: 0
No heightmargin: 0 0 0 .25rem
Add a small margin to the lefttransition: 250ms all ease
If anything changes then animate it over 0.25 secondswidth: 0
No widthvertical-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 flexboxflex-flow: row wrap
If the box isn’t big enough then wrap the child elementsjustify-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
andmenuDown
-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 ofdisplay: 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.
Hi Adam, Thank you for sharing this article it help a lot 🙂
Very interesting. There is one problem, the font colour is such a fine shade of elephant’s breath that is almost impossible to read.
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
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?
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?
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!
What happens when setting a width to the header? Did you use max-width or width?
Your article is helpful. Nice work keep it up 🙂
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!
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?
The menu should be hidden by default. Check you’ve got the correct code for the header.
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
Thanks for the feedback
Is there a possibility to get the full code? im having issues making it completely work
On my note pad++ when i load the complete code it does not work.. Please can i get the full source code?
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
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 !!!
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!
JQuery isn’t best choice for doing responsive navbar, you should use Javascript, it s much much easier.
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.
I am having this trouble:
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.
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.
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.
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?
Should tag include the navigation or should they be kept seperate?
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!
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
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.
Thanks. I’ll get that fixed ASAP.
Hi Adam,
why you do “height: auto !important;” and “height: 100%;” at the body tag?
Great tutorial!
Thank you!
Iven
Hi Iven, it’s just a snippet I’ve picked up along the way to ensure the page is standard across all browsers.
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?
You can simply use CSS classes to shorten the code, but then you’re adding more into your HTML.
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