Responsive Website Navigation Using CSS & JavaScript

Responsive Navigation

Recently, I was tasked with a project of making an existing website “mobile friendly”. As most every web developer well knows, this type of project is not an ideal circumstance for making a site display nicely on mobile and tablet devices. It’s much easier to build a responsive solution on a new website, rather than trying to put a bandage on an existing site to “make it work”. However, building a new solution isn’t always feasible, and we must adapt to each project and work with what we have at our disposal. Luckily, my project was one that I had originally authored, so I had familiarity with the code, and had a much easier time updating the necessary files.

Beyond implementing a viewport meta tag and mobile-specific CSS, I needed a solution for the website navigation, which was a standard horizontal navigation bar of <li> elements, including subnavigation for some sections. Initially, this seemed to be a difficult hurdle to overcome, but in the end, I implemented a solution for the navigation that involved a bit of CSS and JavaScript, and required minimal updates to actual page structure.

Before reading on (or if you just want to see the full code), it may be helpful to you if you grab the demo project I created, which is available on GitHub. I’ll briefly outline some highlights of the code in my explanation of the solution below, but you’ll want to actually look at the full solution to get the best feel for how everything is styled and wired up. Plus, you can use the demo project code as a starting point in your own projects, if you so desire.

Fork Project on GitHub

Now, let’s get to the solution…

Step 1: Add Side Navigation and Menu Bar

First, I added two main divs to each page. In my project, I had set things up relatively intelligently using PHP, so the content of the head tag and even the opening of the body tag were included in the master template that was already included on each page. This made adding these two divs a snap, requiring me to update only the one master file.

Below are the two divs I added. I put them right inside the body tag, before the main wrapper that contained all of the page content. As you’ll notice in reading on, the visibility of these two divs is based on whether or not the page is at a handheld size or not, with the side nav being toggled by means of the mobile_menu button.

<div id="side_nav">
  <div id="side_nav_close"><div class="label">Close</div></div>
</div>
<div id="menu_bar">
    <div id="mobile_menu"></div>
    <div id="mobile_top"></div>
</div>

Step 2: Style the Navigation and Menu Bar Elements

Next, I added new CSS styles to account for a more responsive experience. The styles were set up so a handheld device was set using a media query with max-width of 600px. I won’t list them all of the CSS out here, but in short, here are the rules set for the CSS:

When on Tablet or Desktop Browser:

  • Side nav display set to none
  • Menu bar display set to none
  • Nav links styled to be horizontal list with subnav shown via hover state (desktop) or on click (tablet)
  • Header display set to block

When on a Handheld Device:

  • Side nav display set to block
  • Menu bar display set to block, with fixed position to stay at the top of the window
  • Nav links styled to be vertical list with dropdown arrows for subnav
  • Header display set to none

Step 3: Add Custom JavaScript

Lastly, for this particular solution, I had to introduce some JavaScript logic to do some behind-the-scenes magic. What kind of magic? I’m glad you asked…

Listen for Window Size Change
I needed a way to know when my page elements were hidden/shown to handle my navigation elements accordingly (more on that shortly). Well, in the spirit of true responsive design, I didn’t want to assume that the window size a user had on page load was the window size forever. So I attached a window resize listener, which called a function to check the visibility of key page elements so the JavaScript would know whether or not the page was on a handheld device.

Move Top Nav Links from Header to Side Nav
Another key reason I used JavaScript was to open up the ability to use the same set of top navigation links in both the full and handheld version of the site. I mean really, why duplicate that code?

To do this, I added logic inside of the aforementioned window resize function that would literally move the <ul> list from the header to the side nav, and back, depending on whether or not the page was on a handheld device.

Toggling the Side Nav
Since the side nav wasn’t always supposed to be visible, I needed a way to toggle it back and forth. So, I attached a click handler to the “menu” icon (included in the fixed menu bar), which toggled the visibility of the side nav.

Enable Side Nav Subnav Menu Expansion
When on a handheld device, the nav list was styled to hide the subnav menus by default. Well the JavaScript takes it one step farther, and dynamically adds an expand/contract arrow on the nav items that have subnav menus. This arrow has a click event handler attached to expand and contract the subnav so the user can easily browse all levels of the navigation.

Enable Top Nav Links for Tablet Devices
As you know, tablet devices don’t really do well with hover states. And since my top navigation was set up with hover states for subnav, I had to do a little JavaScript magic to override the default click event on the main-level navigation item. This made it so on click, I could show the subnav list rather than accepting the default action that would take the user to the link associated with the main-level link.

Include “Back to Top” Button in Mobile Menu Bar
When you’re on a handheld device and are looking at a web page with a lot of content, you know how much of a pain it is to scroll all the way back to the top of the page. As a perk to the user experience, I added a “back to top” button (arrow icon) in the mobile menu bar. You’ll note that the mobile menu bar was set to be fixed to the top of the window. And rather than having the “back to top” button always present, I added some JavaScript logic to only have it show when the user had scrolled down the page 100 or more pixels.

Wrapping Up

While this solution won’t necessarily work for every website out there, I found it to be a relatively painless solution for sites with simple navigation structures (one or two levels). It’s a bit more JavaScript than I would have liked, but in the end, I think it was worth it for a better user experience on handheld devices, not to mention helping to not have to duplicate the entire navigation structure for both top and side nav.

I hope you find this helpful for setting up a basic responsive navigation structure for your sites. And if you find any better or more elegant solutions, I’d love to hear about them.

Until next time, happy coding!

2 Responses to this post:

  • Chuck says:

    I tried out your interesting solution on my Mac using Firefox, Safari, iCab and Chrome. Unfortunately, the toggle does not appear to function.

  • Chuck, I’m not sure what to tell you. I downloaded the zip file from the GitHub link in the article, then tested it and had things work just fine. Might I recommend opening up your developer tools to see if you get any console error messages, etc?

Leave a Comment