Toggle Nav No JS HTML

Toggle Navigation – No JavaScript

This article is one in a series of posts highlighting the branding, design and development process behind this website.  Read more at Joe Snell – Branding & Front End Development.

Toggle Nav NO JS - CodePen ImageIn this tutorial, I will demonstrate a simplified version of the responsive toggle navigation pattern I am using on my website. I will show how I built this navigation pattern without using JavaSript and how I utilized it within my WordPress Theme. I used Sass, Compass and custom CSS to build my navigation, but I’ve chosen to simplify the CSS and HTML of the demonstration so it will be easier for others to duplicate and re-use in their projects. Below is a live demo via CodePen:
[CodePen height=300 show=result href=ktGdx user=joesnellpdx ]

When building a responsive website, one of the many design decisions that must be made is how to handle navigation. There are many of design patterns to choose from. Brad Frost, responsive web ninja, put together a great article regarding Responsive Navigation Patterns and a resource for some of those patterns on This Is Responsive.

When I was putting pen to paper on my redesign, I had always envisioned using a toggle navigation pattern when viewing my site on small screens. I began with a JavaScript approach to the navigation pattern, but eventually switched to use a CSS only approach without using JavaScript and utilized it within my WordPress Theme.

I was inspired to go with a CSS / no JS approach to my toggle navigation after reading This Is An Updated Website by Brad Frost and Build A Smart Mobile Navigation Without Hacks by Aaron Gustafson. Coincidently, since building my navigation pattern, another great resource on the utilization of CSS navigation patterns was written by David Bushnell – Implementing Off-Canvas Navigation for a Responsive Website.  These posts do a tremendous job explaining the benefits and pitfalls of using a CSS only navigation pattern, so I won’t get into that in this tutorial.

To begin the tutorial, set up a basic HTML structure. For those familiar with constructing WordPress themes, build a similar structure with the header.php, index.php and footer.php files. Hopefully, this should be somewhat self-explanatory:


<div id="main" class="main demo">
  <header id="header" class="header-demo">
    <!-- Header  Content Here -->
  </header>
  <section id="content" class="content">
    <!-- Main Content Here -->
  </section>
  <footer id="footer" class="footer">
    <!-- Footer Content Here -->
  </footer>
</div>

The next step is to add the <header> content by inserting a site title, the site navigation (<ul> class=“menu”><ul>), and the ‘menu-link.’ The ‘menu-link’ will be used to toggle open the navigation menu by targeting #menu – the navigation. In WordPress, see the comments below for substituting the <ul> with the ‘primary’ theme menu:


<header id="header" class="header-demo">
  <h3>Site Title</h3>
  <a id="jump-top" href="#menu" class="menu-link ">Menu</a>
  <nav id="main-nav" roll="navigation" class="main-nav">
    <!-- In WordPress, substitute the following <ul> with the ‘primary’ navigation by inserting the following ('primary' refers to the menu slug given in the WordPress theme – dashboard > appearance > menus):
    <?php wp_nav_menu( array( 'theme_location' => 'primary', 'container' => '', 'menu_id' => 'menu' ) ); ?>
    -->
    <ul id="menu" class="menu">
      <li><a href="#">Home</a></li>
      <li><a href="#">Blog</a> </li>
      <li><a href="#">Products</a></li>
      <li><a href="#">About Us</a></li>
      <li><a href="#">Contact</a></li>       
    </ul>
  </nav>
</header>

Now that the base structure is set up, the next step is to add some CSS. I’m working with the assumption that some type of reset or base CSS is being used. Feel free to use my Utility CSS for this demonstration. The CSS below will display the <header> as a bar with a set height. By absolutely positioning the ‘menu-link’ and giving it z-index:1001, it will ensure the ‘menu-link’ is ‘above’ the header and click/touch accessible, while giving the appearance it rests within the <header> Additionally, I’ve also styled our navigation <a> elements:


.header-demo {
  height: 3em;
  background-color: #999999;
}
.header-demo h3 {
  float: right;
  margin: 0;
}
.menu-link {
  color: white;
  text-shadow: none;
  background-color: black;
  padding: 0.75em 0.75em 0;
  height: 3em;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1001;
}
.menu-link:hover {
  text-decoration: none;
  background-color: #222222;
}
.menu li a {
  color: #999999;
  text-shadow: none;
  text-decoration: none;
  background-color: #222222;
  display: inline-block;
  height: 2em;
  line-height: 1em;
  padding: .4em;
  border-bottom: 1px solid #333333;
  width: 100%;
}
.menu li a:hover {
  color: #aaa;
  background-color: #333333;
}

The page should now be taking shape, although the navigation menu may look a little wonky at this point.

To toggle the navigation, I am using the :target attribute and the id’s I assigned in the HTML structure. I am using body:not(:target) for the base items to prevent style bleed. This comes directly from Aaron Gustafson’s Build A Smart Navigation Without Hacks:

Sure, if a browser supports media queries, it probably supports :target, but just in case, I opted to preface every relevant style rule withbody:not(:target) (which would only be matched if the browser supported target selection).

To place the <ul> correctly, I’ve absolutely positioned it just below the <header> by giving it padding-top:3em; matching the <header>‘s height and stretching it across the screen with left: 0; and right: 0;. Then, I use CSS to hide the <li> elements and, therefore, hide the navigation menu from view – the goal for its non-targeted state:


body:not(:target) #menu {
  margin: 0;
  padding-top: 3em;
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
}
body:not(:target) #menu li {
  width: 100%;
  height: 0;
  line-height: 0;
  overflow: hidden;
}

To make the toggle navigation menu come alive, I next style the corresponding :target li elements to display them vertically when toggled:


body:not(:target) #menu:target li {
  height: 2em;
  line-height: auto;
  overflow: visible;
}

The primary components of the responsive toggle navigation and the corresponding CSS are in place – a toggle menu is in effect. Selecting the ‘menu link’ will now trigger the menu drop-down.

In order to close the menu without having to click on one of the menu links, I’ll need to add a special component. Taken again from Build A Smart Mobile Navigation Without Hacks, I first add a new link .back to the bottom of the navigation <ul>. This new link will be used to ‘close’ the toggle menu. Using WordPress, this link can be manually added by going to dashboard > appearance > menus in WordPress.


<ul id="menu" class="menu">
  <li><a href="#">Home</a></li>
  <li><a href="#">Blog</a></li>
  <li><a href="#">Products</a></li>
  <li><a href="#">About Us</a></li>
  <li><a href="#">Contact</a></li>
  <li class="back"><a href="#header">back</a></li>
</ul>

To get this new link to work correctly, add the following CSS to position it above the content:


body:not(:target) #menu:target .back {
  height: 0;
  line-height: 0;
}
body:not(:target) #menu:target .back a {
  width: 100%;
  background-color: transparent;
  border: none;
  height: auto;
  position: absolute;
  top: -101em;
  bottom: -101em;
  left: 0;
  right: 0;
  text-indent: -999em;
  z-index: -1;
}

The link now works when clicking / touching the content area, but not the header area. To fix this, first add z-index: 1000; to the existing body:not(:target) #menu in the CSS:


body:not(:target) #menu {
  margin: 0;
  padding-top: 3em;
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  z-index: 1000;
}

Next, add a new CSS item, body:not(:target) #menu:target, below body:not(:target) #menu li a:


body:not(:target) #menu:target {
  z-index: 1001;
}

The toggle navigation is fully operational. To improve the UX, I’ve added a transition effect to the toggle. Although I use Sass and Compass, this is the extended CSS transition effect added to the corresponding <li> elements.


body:not(:target) #menu li {
  width: 100%;
  height: 0;
  line-height: 0;
  overflow: hidden;
  -webkit-transition: height 0.25s;
  -moz-transition: height 0.25s;
  -o-transition: height 0.25s;
  transition: height 0.25s;
}

And:


body:not(:target) #menu:target li {
  height: 2em;
  line-height: auto;
  overflow: visible;
  -webkit-transition: height 0.25s;
  -moz-transition: height 0.25s;
  -o-transition: height 0.25s;
  transition: height 0.25s;
}

To make this toggle navigation responsive, I’ve inserted a media query breakpoint from which I’ve removed the toggle menu entirely and replaced it with standard navigation. I’ve also injected some CSS to alter the display properties of the elements:


@media screen and (min-width: 42em) {
  .menu-link {
    display: none;
  }
  body:not(:target) #menu {
    padding-top: 0;
  }
  body:not(:target) #menu li {
    display: inline;
    border: none;
  }
  body:not(:target) #menu li a {
    color: #555555;
    font-weight: bold;
    text-shadow: inherit;
    line-height: 1em;
    padding: .75em;
    height: 2em;
    width: auto;
    border: none;
    background-color: transparent;
  }
  body:not(:target) #menu li a:hover {
    color: black;
  }
  body:not(:target) #menu .back {
    display: none;
  }
}

This is now a fully functional responsive toggle navigation without using JavaScript. Again, below is a live demo via CodePen:

[CodePen height=300 show=result href=ktGdx user=joesnellpdx ]

Hopefully, this tutorial has been helpful in demonstrating how to build and deploy a responsive toggle navigation without using JavaScript. If you have suggestions on how to improve the code, found this tutorial helpful or have any other comments, I’d love to hear from you in the comments section below.

I’d like to thank Brad Frost and Aaron Gustafson for their inspiration and resources:

Brad Frost:
This Is An Updated Website
Responsive Navigation Patterns
This Is Responsive – Navigation

Aaron Gustafson:
Build A Smart Mobile Navigation Without Hacks