We have a good start on the responsive design. The menu at the smallest screen sizes breaks down into a 2x4 grid. It fits nicely on the screen, but between that and the the branding it takes up an awful lot of space. We open it up on the iOS simulator and see that in some cases you can't see any actual content at all.

We take a look at a few resources on how to handle navigation patterns, like Brad Frost's article Responsive Navigation Patterns and Jason Weaver's Off Canvas. We also look at a cool demo on MDN called Paperfold.

We add an additional link to the navigation we ultimately call "Navigation 'n' Search" which will act as the button to reveal the mobile navigation when tapped. Through media query breakpoints, we hide and show this button as needed.

The toggling of the navigation we'll mostly handle with JavaScript. A little risky as it alienates those on small screens with JavaScript disabled - but I'm just going with it. That number is so small (smaller than desktop without JavaScript, which is certainly less than 1%) that I'm just going to be a jerk and run with it.

All we really do with JavaScript is toggle a class name. That what I like to think of as state-driven CSS development. All the control of what is shown and when and how is handled with CSS. JavaScript just sets a class to declare the current state.

We spend a bunch of time tinkering with adding in the "paperfold" CSS, getting it working correctly, and then placing the search in a gap we create above the main content through some padding.

Ultimately, the sizing and position is tweaked to fit even nicer and a small close button is added. I go back and forth in my head with providing UI for toggling states on things like this. One one hand, now that the user has revealed the navigation, why would they need to close it? They've already seen it. If they don't want to use it, they can just flick past it. On the other hand, I find it kind of annoying when I can't toggle states like this on other apps (for some reason) so I'm inclined to provide a mechanism to do it.

Comments

  1. Daz
    Permalink to comment#

    Hi Chris,

    Im using a slightly different method to show/hide the menu.

    My javascript is

    jQuery(document).ready(function($){
    /* toggle nav */
    $("#menutoggle").on("click", function(){
    $("#nav").slideToggle(1000);
    $(this).toggleClass("active");
    });
    
    });
    

    And my HTML

    <div id="navtoggle" class="cf">
    <div class="section">
    <a href="#" id="menutoggle">Menu</a></div>
    </div>
                                                
    <div id="nav" class="cf"> 
    <ul class="menu">
    <li class="item-102"><a href="/basecamp/index.php/themes" >Themes</a></li><li class="item-103"><a href="/basecamp/index.php/icons" >Icons</a></li><li class="item-104"><a href="/basecamp/index.php/logos" >Logos</a></li><li class="item-105"><a href="/basecamp/index.php/support" >Support</a></li><li class="item-109"><a href="#" >Blog</a></li><li class="item-110"><a href="#" >Contact</a></li></ul>
    </div>
    

    It works perfect however after selecting the toggle to hide the menu it stays hidden when I re-size the browser window! I basically need the toggle to reset to show the menu when I stretch the browser window beyond the breakpoint.

    Any suggestions please?

  2. Daz
    Permalink to comment#

    I think I figured out a solution using a min-width media query and adding

    display: block !important;

    Is the use of !important ok to use?

  3. ryandolankayak
    Permalink to comment#

    Hi Chris,
    Sorry to bother you but I followed along with this video but just cant seem to get the navigation to show anything when clicked on. I have double checked everything to your but cant seem to make anything of it. Would you mind just looking at what I have real quick and see if anything stands out?

    my css:

    nav {
    background-color: rgb(92,107,127); // Old browsers
    @include filter-gradient(#5c6b7f, #40536f, vertical); // IE6-8
    // IE9 SVG, needs conditional override of ‘filter’ to ‘none’
    $experimental-support-for-svg: true;
    @include background-image(linear-gradient(top, rgba(92,107,127,1) 0%,rgba(64,83,111,1) 100%));
    -webkit-box-shadow: 1px 5px 6px -6px black;
    -moz-box-shadow: 1px 5px 6px -6px black;
    box-shadow: 1px 5px 6px -6px black;
    border-top: 1px solid #666666;
    border-bottom: 1px solid #666666;

    // Individual Links In Menu Styles
    a {
    display: inline-block;
    width: (100%/6);
    text-align: center;
    padding: 15px 30px 15px 30px;
    color: $white;
    @include font-stack-mainfont;
    font-weight: 700;
    font-size: 17px;
    border-right: solid 1px #445368;
    @include text-shadow(rgba(black, 0.1) 1px 1px 0, rgba(black, 0.1) 1px 1px 0, rgba(black, 0.1) 1px 1px 0);
    @include breakpoint(iphone) {
    width: (100%/1);
    border-bottom: solid 1px #445368;
    }
    }
    .show-hide-navigation {
    display: none;
    }
    @include breakpoint(iphone) {
    a:not(.show-hide-navigation) {
    display: none;
    body.show-nav & {
    display: inline-block;
    }
    }
    .show-hide-navigation {
    display: inline-block;
    width: 100%;
    }

    }               
    

    my JS:

    $(“#show-hide-navigation”).on(“click”,function() { $(“body”).toggleclass(“show-nav”); });

    thanks

    • ryandolankayak
      Permalink to comment#

      Also when I inspect the element on chrome like you did I click on my navigation and it spits out an error:
      “Uncaught TypeError: Object [object Object] has no method “toggleclass”

      and the code its highlighting is the fitvids one

    • marinade
      Permalink to comment#

      Ryan your issue might be how its loading the jquery. I had a similar issue because I was following Chris verbatim. But because he uses codekit and I am not I had to do things differently. In this case Chris didn’t need to introduce the script using this line in the index.php file after global.js introduction. If all else fails you can always hit up irc channel #jquery. They are really helpful.

      <script src="/js/jquery.fitvids.js"></script>
      
    • marinade
      Permalink to comment#

      There is some issue with the $ sign also so I will show you what works for me. (actually everything works for me except the x button that is supposed to close out the search input and bring it back to the search icon. but here it is anyways

      jQuery(function($) {
      $("article").fitVids();
      });
      
      var openSearch = $(".open-search, #x-search");
      
      function toggleSearch() {
          $(".search").toggleClass("open");
          openSearch.toggle();
          $(".close-search").toggle();
      }
      
      openSearch.on("click", function() {
          toggleSearch();
      })
      
      $("#show-hide-navigation").on("click", function() {
      $("body").toggleClass("show-nav");
      })
      

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences like this:

```
<script>
  function example() {
    element.innerHTML = "<div>code</div>";
  }
</script>
```

We have a pretty good* newsletter.