Experiment No 5

Top Drawer

Menu

Aim

To demonstrate smoother reveal menus in small contexts using CSS3 rather than animating with JavaScript.

Ingredients

  • CSS Transforms
  • Modernizr
  • JavaScript (I used jQuery, but you could easily do this with VanillaJS)

Method

Tap the menu icon in the top right. The click event will assign the class of active to the drawer container which alters the translate value to bring it into view.

Modernizr will detect whether the user's device is capable of CSS transforms, if it isn't we simply show and hide the menu after the button is pressed - no point in animating if it isn't going to work smoothly.

To set up the experiment we need to create a scenario similar to a box of matches, the box (in our case the top black heading) covers the match drawer beneath (our div with a class of drawer). We build the page as normal but pull the drawer up and off the canvas using the CSS Translate property and show it again in the active state for the div using Translate back to it's regular position. CSS Transitions allow us to create the smooth animation between the states.

HTML

<div class="top">
  ...
  <a href="#" class="menu"><span>≡</span> Menu</a>
</div>
</header>

<div class="drawer">
<nav>
  <ul class="nav nav-tabs nav-stacked">
    <li><a href="#">Menu Item</a></li>
    <li><a href="#">Menu Item</a></li>
    <li><a href="#">Menu Item</a></li>
    <li><a href="#">Menu Item</a></li>
    <li><a href="#">Menu Item</a></li>
  </ul>
</nav>
...
              
          

CSS

.top {
  background: #212121;
  color: #fff;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  z-index: 2;
  overflow: hidden;
}
a.menu {
  position: absolute;
  z-index: 3;
  border:1px solid white;
  text-decoration: none;
  top: 1.6em;
  right: 1.6em;
  color: #fff;
  text-transform: uppercase;
  font-size: 0.65em;
  padding: 0.4em 0.7em;
  border-radius: 4px;
}
a.menu span {
  font-size:1.6em;
  vertical-align: -0.15em;
}
nav ul {
list-style:none;
}
nav ul li a {
display: block;
text-decoration: none;
background: rgba(0,0,0,0.3);
color: white;
padding: 1em;
margin-bottom: 1px;
}
.drawer {
  -webkit-transform: translate3d(0, -131px, 0);
  -moz-transform: translate3d(0, -131px, 0);
  -o-transform: translate3d(0, -131px, 0);
  transform: translate3d(0, -131px, 0);
  -webkit-transition:-webkit-transform 0.25s linear;
  -moz-transition:-moz-transform 0.25s linear;
  -o-transition:-o-transform 0.25s linear;
  transition:transform 0.25s linear;
}
.drawer.active {
  -webkit-transform: translate3d(0,129px,0)
  -moz-transform: translate3d(0,129px,0)
  -o-transform: translate3d(0,129px,0)
  transform: translate3d(0,129px,0)
}

/* Fallbacks */

.no-csstransforms .top {
  position: static;
}

.no-csstransforms .drawer nav {
  display: none;
}

.no-csstransforms .drawer.active nav {
  display: block;
}