Creating a material design sidenav using pure JavaScript
Published: 2021-05-24 01:06:41

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](https://fonts.google.com/icons?selected=Material+Icons) webfont for the icons
```html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
```
Here's the code for the sidenav:
```html
<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>
```
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. 
```css
.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)
  }
```

Then some basic styles for the sidenav links

```css
.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;
  }
```

Let's define a class for an active link

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

Sidenav main code

```css
  .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;
  }
```
And, let's adjust the icons a bit

```css
  .sidenav ul li a i {
    font-size: 24px;
    position: relative;
    bottom: -7px;
    margin-right: 10px
  }
```

## The fun part - JavaScript!

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

```js
  var sidenav_overlay = document.createElement('div');
  sidenav_overlay.className = "sidenav-overlay";
  sidenav_overlay.id = "sidenav-overlay";
  document.body.appendChild(sidenav_overlay);
```

And, the sidenav code

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

```js
  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)};
    }
  }
```
... and to close the sidenav...

```js
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);
    },
}
```

Final code: 
```html
<!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>
```