Off canvas responsive pattern example

by Jorge Arévalo

HTML

<nav id="drawer" class="dark_blue">
      <h2>Off Canvas</h2>
      <p>Click outside the drawer to close</p>
    </nav>

    <main class="light_blue">
      <a id="menu">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
          <path d="M2 6h20v3H2zm0 5h20v3H2zm0 5h20v3H2z"/>
        </svg>
      </a>
      <p>Click on the menu icon to open the drawer</p>
    </main>

CSS

@import url(https://fonts.googleapis.com/css?family=Roboto);

html, body {
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Roboto', sans-serif;
}

.title {
  font-size: 2.5em;
  text-align: center;
}

.box {
  min-height: 150px;
}

.dark_blue {
  background-color: #2A457A;
  color: #efefef;
}

.light_blue {
  background-color: #099DD9;
}

html, body, main {
        height: 100%;
        width: 100%;
      }
      a#menu svg {
        width: 40px;
        fill: #000;
      }
      nav, main {
        padding: 1em;
        box-sizing: border-box;
      }

      /*
       * Off-canvas layout styles.
       */

      /* Since we're mobile-first, by default, the drawer is hidden. */
      nav {
        width: 300px;
        height: 100%;
        position: absolute;
        /* This trasform moves the drawer off canvas. */
        -webkit-transform: translate(-300px, 0);
        transform: translate(-300px, 0);
        /* Optionally, we animate the drawer. */
        transition: transform 0.3s ease;
      }
      nav.open {
        -webkit-transform: translate(0, 0);
        transform: translate(0, 0);
      }

      /* If there is enough space (> 600px), we keep the drawer open all the time. */
      @media (min-width: 600px) {

        /* We open the drawer. */
        nav {
          position:relative;
          -webkit-transform: translate(0, 0);
          transform: translate(0, 0);
        }

        /* We use Flexbox on the parent. */
        body {
          display: -webkit-flex;
          display: flex;
        }

        main {
          width: auto;
          /* Flex-grow streches the main content to fill all available space. */
          flex-grow: 1;
          
          /* What is the difference between those 2 options and just width:100%? */
        }

        main > #menu:after {
          content: 'The drawer stays open if width > 600px';
        }
        main p, nav p {
          text-decoration: line-through;
        }
      }

JavaScript

/*
       * Open the drawer when the menu ison is clicked.
       */
      var menu = document.querySelector('#menu');
      var main = document.querySelector('main');
      var drawer = document.querySelector('#drawer');

      menu.addEventListener('click', function(e) {
        drawer.classList.toggle('open');
        e.stopPropagation();
      });
      main.addEventListener('click', function() {
        drawer.classList.remove('open');
      });