DEV Community

loading...
Cover image for Creating a material design sidenav using pure JavaScript

Creating a material design sidenav using pure JavaScript

Manu
π™Όπš’ πš—πšŠπš–πšŽ πš’πšœ π™ΌπšŠπš—πšž, πšŠπš—πš 𝙸'πš– 𝚊 𝟷𝟹-πš’πšŽπšŠπš›-πš˜πš•πš πšπšžπš•πš• πšœπšπšŠπšŒπš” 𝚍𝚎𝚟 πš πš‘πš˜ πš˜πš πš—πšœ πš πšŽπš‹πšœπš’πšπšŽπšœ πšŠπš—πš πšœπšŽπš›πšŸπšŽπš›πšœ πšŠπšŒπš›πš˜πšœπšœ πšπš‘πšŽ πš πš˜πš›πš•πš. 𝙸 πšŽπš—πš“πš˜πš’ πš™πš›πš˜πšπš›πšŠπš–πš–πš’πš—πš πš’πš— π™·πšƒπ™Όπ™», π™²πš‚πš‚, πš•πš˜πšπšœ 𝚘𝚏 π™Ήπš‚, 𝚁𝚎𝚊𝚌𝚝, 𝙿𝙷𝙿, πšŠπš—πš πš‚πš€π™»
・4 min read

The sidenav components are designed to add side content to a fullscreen app. The drawer component is designed to add side content to a small section of your app.

Here's how to achieve this using pure JS!

Codepen: https://codepen.io/ManuTheCoder/pen/YzZVyjo

Step 1 - Creating the HTML

We're going to use the Material Icons webfont for the icons

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
Enter fullscreen mode Exit fullscreen mode

Here's the code for the sidenav:

<a href="#" onclick="sidenav.open('demo_sidenav')">Open Sidenav</a>
<div id="demo_sidenav" class="sidenav">
  <ul>
    <li><a href="#" class="active_link"><i class="material-icons">home</i> Home</a></li>
    <li><a href="#"><i class="material-icons">book</i> News</a></li>
    <li><a href="#"><i class="material-icons">forum</i> Forum</a></li>
    <li><a href="#"><i class="material-icons">help</i> Help</a></li>
    <li><a href="#"><i class="material-icons">settings</i> Settings</a></li>
  </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

If you noticed one link has a class containing active_link. This highlights the a link to make it look active. This is optional, though

Step 2 - Creating the CSS

So, we're going to create a overlay for the sidenav. Notice that it isn't in the HTML section. This is because we are going to create an element using javascript's createElement feature.

.sidenav-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index:99;
    background: #212121;
    transition: all .2s;
    background: rgba(0,0,0,0.3)
  }
Enter fullscreen mode Exit fullscreen mode

Then some basic styles for the sidenav links

.sidenav ul {
    list-style-type: none;
    padding:0;
  }
  .sidenav ul li a {
    line-height: 45px;
    text-decoration: none;
    color: #6e6e6e;
    padding: 0 10px;
    display: block;
    margin: 5px;
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
    border-radius: 5px;
  }
Enter fullscreen mode Exit fullscreen mode

Let's define a class for an active link

.active_link {
    background: rgba(10, 113, 209, .1);
    color: #0a71d1 !important;
    pointer-events: none
  }
Enter fullscreen mode Exit fullscreen mode

Sidenav main code

  .sidenav {
    overflow-y:scroll;
    width: 300px;
    height: 100vh;
    display: block;
    position:fixed;
    top:0;
    left: -300px;
    z-index: 9999999999999999;
    transition: left .2s;
    z-index:999;
    background: white;
  }
Enter fullscreen mode Exit fullscreen mode

And, let's adjust the icons a bit

  .sidenav ul li a i {
    font-size: 24px;
    position: relative;
    bottom: -7px;
    margin-right: 10px
  }
Enter fullscreen mode Exit fullscreen mode

The fun part - JavaScript!

Let's create a sidenav overlay using the createElement feature in JavaScript

  var sidenav_overlay = document.createElement('div');
  sidenav_overlay.className = "sidenav-overlay";
  sidenav_overlay.id = "sidenav-overlay";
  document.body.appendChild(sidenav_overlay);
Enter fullscreen mode Exit fullscreen mode

And, the sidenav code

So, we're going to create an object sidenav. This will be used to open and close the sidenav

  const sidenav = {
    open: function(selector) {
      document.getElementById(selector).style.left = "0";
      var x = document.getElementById('sidenav-overlay');
      x.style.display = "block";
      x.style.opacity = 0;
      setTimeout(function() {x.style.opacity = 1;}, 10)
      x.onclick = function() {sidenav.close(selector)};
    }
  }
Enter fullscreen mode Exit fullscreen mode

... and to close the sidenav...

const sidenav = {
   // ...
close: function(selector) {
      document.getElementById(selector).style.left = '-300px';
      var x = document.getElementById('sidenav-overlay');
      x.style.opacity = 0;
      setTimeout(function() {x.style.display = "none";}, 200);
    },
}
Enter fullscreen mode Exit fullscreen mode

Final code:

<!DOCTYPE html>
<html>
  <head>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <style>
      .sidenav-overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index:99;
        background: #212121;
        transition: all .2s;
        background: rgba(0,0,0,0.3)
      }
      .sidenav ul {
        list-style-type: none;
        padding:0;
      }
      .sidenav ul li a {
        line-height: 45px;
        text-decoration: none;
        color: #6e6e6e;
        padding: 0 10px;
        display: block;
        margin: 5px;
        font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
        border-radius: 5px;
      }
      .active_link {
        background: rgba(10, 113, 209, .1);
        color: #0a71d1 !important;
        pointer-events: none
      }
      .sidenav {
        overflow-y:scroll;
        width: 300px;
        height: 100vh;
        display: block;
        position:fixed;
        top:0;
        left: -300px;
        z-index: 9999999999999999;
        transition: left .2s;
        z-index:999;
        background: white;
      }
      .sidenav ul li a i {
        font-size: 24px;
        position: relative;
        bottom: -7px;
        margin-right: 10px
      }
    </style>
  </head>
  <body>
    <a href="#" onclick="sidenav.open('demo_sidenav')">Open Sidenav</a>
    <div id="demo_sidenav" class="sidenav">
      <ul>
        <li><a href="#" class="active_link"><i class="material-icons">home</i> Home</a></li>
        <li><a href="#"><i class="material-icons">book</i> News</a></li>
        <li><a href="#"><i class="material-icons">forum</i> Forum</a></li>
        <li><a href="#"><i class="material-icons">help</i> Help</a></li>
        <li><a href="#"><i class="material-icons">settings</i> Settings</a></li>
      </ul>
    </div>
    <script>
      const sidenav = {
        open: function(selector) {
          document.getElementById(selector).style.left = "0";
          var x = document.getElementById('sidenav-overlay');
          x.style.display = "block";
          x.style.opacity = 0;
          setTimeout(function() {x.style.opacity = 1;}, 10)
          x.onclick = function() {sidenav.close(selector)};
        },
        close: function(selector) {
          document.getElementById(selector).style.left = '-300px';
          var x = document.getElementById('sidenav-overlay');
          x.style.opacity = 0;
          setTimeout(function() {x.style.display = "none";}, 200);
        },
      }
      var sidenav_overlay = document.createElement('div');
      sidenav_overlay.className = "sidenav-overlay";
      sidenav_overlay.id = "sidenav-overlay";
      document.body.appendChild(sidenav_overlay);
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Discussion (0)