Mobile/Tablet layout prototype

Requirements: 1. Header is fixed in the top 2. Header has a menu button for opening/closing the left sidebar nav menu 3. Tap on the menu button, the left sidebar nav appeared by pushes the content to the right 4. Tap on the menu button again or the content will pushing the nav and content back to the left Tested in iPhone8 Plus, iPad Air.

by junhui

HTML

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Mobile Layout Prototype</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>

  <body>
    <div class="absolute-layer wrapper">
      <div class="absolute-layer sub-wrapper">
        <nav>
          <div class="absolute-layer scrollable-y">
            Navigation
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
            <p>Lorem, ipsum dolor.</p>
          </div>
        </nav>
        <header>
          <button id="menuButton">
                    Toggle Menu
                </button> Header
        </header>
        <div class="page-content-wrapper absolute-layer scrollable-y">
          <main>
            start
            <br />
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus consequuntur aliquid amet. Neque modi voluptate sapiente numquam laborum aut, officiis dignissimos voluptatem maiores eos deleniti! Fuga minus quo aspernatur nulla eligendi
              eaque voluptate explicabo dolor, vero temporibus similique nam saepe eos doloremque quis voluptates
              <input type="text" /> officia vel. Nulla mollitia ab, laudantium repudiandae corporis ad corrupti ullam aspernatur atque? Ea, deserunt et! Aliquam doloremque doloribus, placeat qui sequi magnam, fugiat sit at consequuntur porro repellendus
              quia...

CSS

/* Requirements:
 * 1. Header is fixed in the top
 * 2. Header has a menu button for opening/closing the left sidebar
 * nav menu
 * 3. Tap on the menu button, the left sidebar nav appeared by pushes
 * the content to the right
 * 4. Tap on the menu button again or the content will pushing
 * the nav and content back to the left
 *
 * The HTML elements' hierarchy:
 * * root
 *   * .wrapper (absolute, z-index: auto)
 *     * .sub-wrapper (absolute, z-index: auto)
 *       * nav (absolute, z-index: auto)
 *         * .nav-inner-wrapper (absolute, z-index: auto)
 *       * header (relative, z-index: 1)
 *         * .page-content-wrapper
 *           * main
 *           * footer
 *
 * And the stacking context hierarchy:
 * * root stacking context  
 *   * header (relative, z-index: 1)
 *   * nav
 *   * .page-content-wrapper (main, footer)
 * 
 * Read more about stacking context:
 * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
 */

/* Utilites */

/* 
 * The absolute-layer is useful to create an inner scrollable layer,
 * read more from:
 * https://medium.com/@im_rahul/safari-and-position-fixed-978122be5f29
 */

.absolute-layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.scrollable-y {
  -webkit-overflow-scrolling: touch;
  overflow-y: auto;
}

/* Toggle Menu */

/* Both .wrapper and .sub-wrapper is an absolute layer */

.wrapper.menuIsOpen {
  overflow: hidden;
}

.sub-wrapper {
  transition: transform 0.3s ease-out;
}

.wrapper.menuIsOpen>.sub-wrapper {
  transform: translateX(240px);
}

/* Left sidebar - Nav */

/* 
 * Notes:
 * 1. Left sidebar sits in the left side of the content, it's
 * invisible by default. When the menu is open, it pushes the
 * sub-wrapper right to let the nav visible in the viewpoint.
 * 2. nav's inner wrapper should be an abosolute layer and
 * scrollable.
 */

nav {
  width: 240px;
  /* Fixed width */
  position: absolute;
  top: 0;
  bottom: 0;
 ...

JavaScript

const menuButton = document.querySelector("#menuButton");
const wrapper = document.querySelector(".wrapper");
const pageContent = document.querySelector(".page-content-wrapper");

/* Toggle Menu */

menuButton.addEventListener("click", function() {
  if (wrapper.classList.contains("menuIsOpen")) {
    wrapper.classList.remove("menuIsOpen");
  } else {
    wrapper.classList.add("menuIsOpen");
  }
})

/* Touch the page content close the menu */

pageContent.addEventListener("touchstart", function(event) {
  if (wrapper.classList.contains("menuIsOpen")) {
    // Prevent the origin bounce effect, read more:
    // https://stackoverflow.com/a/7771215
    event.preventDefault();

    wrapper.classList.remove("menuIsOpen");
  }
});