Responsive navigation menus come in all different shapes and sizes, you might recall my post on creating a dynamic select menu from an existing menu, which is one method. So let’s visit another. The ‘in-page’ navigation.
Table of contents
Edit: If you’re looking for an even better responsive navigation that supports nested menus, check out my Flaunt JS script.
What is ‘in-page’ navigation?
Depending on your project, a dynamic <select> menu may not be entirely appropriate, there is a massive debate on which way to steer your projects, so let’s open the door for another option. In-page navigation is basically restyling your menu in such a way that it’s responsive, but also looks like part of the design whilst delivering an awesome mobile and touch experience. I say touch because some menus deliver a nice mobile experience, but the rendering jutters and in a way puts a downer on the experience. Mobile experience is meant to be fast and efficient, so let’s cut the junk and build something that really delivers a solution.
Simplicity is key
Creating our desktop navigation
Let’s break out the HTML5 elements and create a neat and basic menu:
Here I’ve used a nice naming convention on our navigation, unordered list and items inside. This gives us nice and easy CSS targeting.
Creating the desktop navigation
I’ll take you through my responsive workflow a little, and depending on your project and how you’re setting up your media queries, this may differ to you slightly.
First I am going to add some basic styling to the nav:
You’ll notice .nav has the ‘display:inline-block’ property, this is so it centralises in the page for the demo, and isn’t entirely necessary for production.
This sets out a nice deep grey/blue coloured navigation for us to work with on the desktop. Done. But now we need a mobile navigation.
Now we’ve established a basepoint for our navigation, we need to think mobile and tablet. Our navigation items at the minute are inline to eachother, but this needs to change for mobile.
To get the navigation to sit ontop of eachother, we need to create a new CSS rule using media queries, to tell the browser/device that anything iPad and under needs to show the navigation elements ontop of eachother - stacked!
This doesn’t require much fiddling, but we’ve introduced a media query:
Depending on the design of your project, you might need to use different media queries, but essentially, this media query saves us from undoing/redoing later styles that we need to re-apply. It tells the browser two things; 1) any styles above 320px, use this styles, and 2) don’t show these styles to anything above 768px, which is anything larger than iPad. This is a pretty good use of the min-width and max-width CSS3 media queries as you can achieve a lot with very little.
What the above CSS does is change our inline navigation items into full-width and stacked items, just what we need.
Expanding and collapse
First we need to create an element to click on, which will act as the popular ‘three-line’ menu approach which is pretty iconic when it comes to mobile users, so it’s a safe bet:
Nice and easy, we create a new <div>, give it ‘nav-mobile’ as the class name (keeping our naming conventions in check) and using the querySelector to append it. It’s pretty safe to use querySelector here as any browser that supports CSS3 media queries I am pretty confident will support querySelector (even IE8 does).
Now we need to style the clickable icon:
I’ve added these styles in the main area of the CSS, not inside any media queries. This is so that the menu can be styled in the main CSS area, and literally tweaked inside our media queries for easy management. It also benefits us again because if you were to style it inside a media query, older browsers would ignore it leaving it unstyled and randomly placed element - which is why it includes ‘display:none;’ by default. This method I’ve found to be the best.
Using an SVG again (pretty confident most browsers will support SVG and media queries, so let’s use it) we create a scalable ‘three-line’ icon. This means we don’t have to do any further optimisation for retina displays.
Going back to our media query, we need to tell it to show our mobile icon for our decided viewport widths:
This simply shows it to the user. But we now we to hide our dropdown list that’s still in clear view, our ‘nav-list’ class:
Obviously I wouldn’t use a separate media query for each one here, but you can see how it works and where we include the declarations.
Now our button is visible, and our navigation list is hidden, let’s move on…
I basically want to setup a simple click handler on the newly appended and styled button so that it opens and closes our navigation when clicked. To do this, I’m not going to use jQuery or animation techniques, for a really nice experience (and instant) I am literally going to change the styles from ‘display:none;’ to ‘display:block;’, and then toggle it back when clicked again.
I’m going to setup a really simple onclick handler to toggle a new ‘nav-active’ class, but first I need to grab some jQuery-style ‘toggleClass’ and ‘hasClass’ functions from a previous post:
I’ll then use the toggleClass method in my onclick handler (using the querySelector again to grab the elements):
The great thing about mobile is they also interpret hover as a touch method, which means if you wanted to add hover capabilities to another nested menu (just like a secondary nested dropdown you could get away with using :hover pseudo selectors to display the nested content).
Here’s the full script for the above tutorial: