Off Canvas Sidebar Nav Pattern

All off canvas patterns solve the problem of space, by placing some content off screen until needed. In this pattern the navigation is off canvas left when the page first loads on smaller screens.

In its place a single menu button that when clicked slides the menu in and the content mostly off screen right. The click event is controlled with a checkbox that's positioned far off the screen.

The HTML

For this pattern we need to work we need to wrap most of our elements inside two divs (wrapper and inner). The navigation sits outside these 2 container divs.

Other than the menu and the toggle button, I've stripped out what's inside each of the divs so you can focus on the structure.

<input id="toggle" type="checkbox" />
<nav>
  <label class="close" for="toggle" onclick><span>X</span> Close</label>
  <ul id="nav">
    <li><a href="">Back to Post</a></li>
    <li class="current"><a href="sidebar-nav.html">Sidebar Nav</a></li>
    <li><a href="sidebar-nav-js.html">Sidebar Nav JS</a></li>
    <li><a href="sidebar+.html">Sidebar+</a></li>
    <li><a href="panels.html">Panels</a></li>
  </ul>
</nav>

<div class="wrapper">
  <div class="inner">
    <header>
      <label class="btn" for="toggle" onclick>Menu</label>
    </header>
		
    <div class="container main-content">
      <div id="content"></div>
      <div id="sidebar"></div>
    </div>
      
    <section class="subfooter"></section>
    <div id="footer"></div>
  </div>
</div>

				

The Default CSS

.btn {
  float: left;
  margin: 1.5em 0 0 0;
  background: #999;
  padding: 0.25em 2%;
  color: #fff;
  cursor: pointer;
  border-radius: 0.25em;
  background-color: #5b5756;
  background-image: -webkit-linear-gradient(top, #6b6766, #5b5756);
  background-image:    -moz-linear-gradient(top, #6b6766, #5b5756);
  background-image:     -ms-linear-gradient(top, #6b6766, #5b5756);
  background-image:      -o-linear-gradient(top, #6b6766, #5b5756);
  background-image:         linear-gradient(top, #6b6766, #5b5756);
}
	
.btn:hover {
  background-color: #7b7776;
  background-image: -webkit-linear-gradient(top, #8b8786, #7b7776);
  background-image:    -moz-linear-gradient(top, #8b8786, #7b7776);
  background-image:     -ms-linear-gradient(top, #8b8786, #7b7776);
  background-image:      -o-linear-gradient(top, #8b8786, #7b7776);
  background-image:         linear-gradient(top, #8b8786, #7b7776);
}


#toggle {
  position: absolute;
  left: -999em;
}

nav {
  position: fixed;
  padding: 5em 0 0 0;
  background: #3b3736;
  width: 75%;
  left: -75%;
  height: 100%;

  -webkit-transition: left 0.5s;
     -moz-transition: left 0.5s;
      -ms-transition: left 0.5s;
       -o-transition: left 0.5s;
          transition: left 0.5s;
}

.close {
  cursor: pointer;
  color: #fff;
}

.close:hover {
  color: #999;
}

.close span {
  border: 2px solid #fff;
  border-radius: 50%;
  padding: 0.2em 0.4em;
}
		
#nav {
  margin: 0.1875em 0 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid #777;
}
		
#nav a {
  text-decoration: none;
  color: #fff;
  padding: 1em 0 1em 5%;
  display: block;
  border-bottom: 1px solid #777;
  height: 4em;
  background-image: -webkit-linear-gradient(top, #4b4746, #3b3736);
  background-image:    -moz-linear-gradient(top, #4b4746, #3b3736);
  background-image:     -ms-linear-gradient(top, #4b4746, #3b3736);
  background-image:      -o-linear-gradient(top, #4b4746, #3b3736);
  background-image:         linear-gradient(top, #4b4746, #3b3736);
}

#nav a:hover {
  background: #4b4746;
  background-image: -webkit-linear-gradient(top, #5b5756, #4b4746);
  background-image:    -moz-linear-gradient(top, #5b5756, #4b4746);
  background-image:     -ms-linear-gradient(top, #5b5756, #4b4746);
  background-image:      -o-linear-gradient(top, #5b5756, #4b4746);
  background-image:         linear-gradient(top, #5b5756, #4b4746);
}

.wrapper {
  width: 100%;
  overflow: hidden;
}

.inner {
  float: right;
  width: 100%;
  margin-right: 0;

  -webkit-transition: 0.5s;
     -moz-transition: 0.5s;
      -ms-transition: 0.5s;
       -o-transition: 0.5s;
          transition: 0.5s;
}
				

The CSS to Toggle the Menu

To slide in the menu we adjust its left position. To slide out the content we adjust its right margin. For both we use the checkbox hack and target the element with a sibling selector.

:checked ~ nav {
  left: 0;
}
	
:checked ~ nav .close {
  position: fixed;
  top: 1.5em;
  left: 4%;
  display: block;
}

:checked ~ .wrapper .inner {
  margin-right: -75%;
}
				

The CSS in Media Queries

Once the screen is wider than 48em we convert the menu to a horizontal navigation bar at the top right of the page.

@media screen and (min-width: 48em) {
  header {
    padding-bottom: 5em;
  }
  
  .logo {
    float: left;
    margin: 1.25em 0;
  }
	
  .btn {display: none;}
	
  :checked ~ .wrapper .inner {
    margin-right: 0%;
    -webkit-transition: 0;
       -moz-transition: 0;
        -ms-transition: 0;
         -o-transition: 0;
            transition: 0;
  }
	
  nav,
  :checked ~ nav {
    float: right;
    position: static;
    background: transparent;
    padding: 0;
    height: auto;
    width: 100%;
    -webkit-transition: 0;
       -moz-transition: 0;
        -ms-transition: 0;
         -o-transition: 0;
            transition: 0;
  }
		
  nav .close,
  :checked ~ nav .close {
    display: none;
  }
		
  #nav {
    position: absolute;
    top: 1.5em;
    right: 2%;
    border: 0;
  }
			
  #nav li {display: inline; float: left;}
  #nav li.current a {color: #7b7776;}
			
  #nav a {
    padding: 0 1.5em;
    display: inline;
    border: 0;
    background: transparent;
  }
				
  #nav a:hover {background: transparent;}

  #sidebar {
    margin-top: 5.5em;
  }
}