Creating a Sidenav menu with Bootstrap
Tags: bootstrap, css, frontend
Published: 2018-08-26 12:35:47

---
title: Creating a Sidenav menu with Bootstrap
published: true
description: A really simple sidenav menu using Bootstrap 
tags: bootstrap, css, frontend
---

So far I've write mostly about Angular and Typescript, and that won't change. But today, I'll bring to you one quickly post about how to do a simple but effective Sidenav in Bootstrap. 

{% github michaeljota/bootstrap-examples %}

In that repo you will find the `sidenav` branch with all the final code.

# What is a Sidenav?

A Sidenav is a collapsible component to place side, often and in this case, navigation content. Bootstrap have a Navbar Menu component that serves for some kind the same purpose, group navigational components, show them by default in a the Navbar, hide them in mobile, and toggle them when interacting with the manu button.

By default, Bootstrap show that menu below the Navbar, pushing the content to make space. The Sidenav instead, overlap the content, sometimes with a backdrop, but not this time. 

# First steps

I'll asume you have a Bootstrap project setup. If you don't, fell free to use the one of the `master` branch of the repo to start. 

I will use the same snipped code from Bootstrap. You can read the documentation of the Navbar component, and copy the started snipped from [here](https://getbootstrap.com/docs/4.1/components/navbar/#supported-content)

You should have a page with a Navbar shows all the navigation items by default if the screen is large, and collapse them otherwise. Also, you should be able to toggle the menu when it's collapsed.

For this example, I will first test it for a extra small screen, so replace the `.navbar-expand-lg` class in the `nav` element, with a `.navbar-expand-sm`. This will indicate Bootstrap, the navbar should be expanded by default for any screen larger than small. 

So, open your DevTools, and set the device to something extra small, like an iPhone 5S. I created another file just to place the sidenav styles, but you can place the code wherever you want. Create a `.sidenav` class, and add it to the `div` element with the `.navbar-collapse`.

# Creating the sidenav

We want to do something that overlaps the screens when gets showed, and we can leverage to `navbar` component have a `position: relative` by default. So we can use `position: absolute` to place it as we want.

```css
.sidenav {
  position: absolute;
}
```

You should see like something is moving, but you can't actually see what it is. To be able to see all the elements, you need to set the position. This is a matter of taste really, but I will just place the menu just bellow the navbar, and expand it to take all the screen available.


```css
.sidenav {
  position: absolute;
  top: 100%;
  height: calc(100vh - 100%) !important;
  left: 0%;
  width: 100%;
}
```

You should now see how menu appear and disappear. This is because Bootstrap applies a `.show` class, that when is not present in the element, the element have a `display: none`. But we can also use it for our intention, of showing the menu from left to right. The `!important` in the height is because Bootstrap modify the style attribute of the element with a custom height.


```css
.sidenav {
  position: absolute;
  top: 100%;
  height: calc(100vh - 100%) !important;
  left: 0%;
  width: 100%;
}

.sidenav:not(.show) {
  left: -100%;
}
```

It don't seem to have any effect. But, actually the element is moving, from left to right. We are just not seeing the animation. I'm still learning about animations, that's why for this simple case I'll use the `transition` property.


```css
.sidenav {
  position: absolute;
  top: 100%;
  height: calc(100vh - 100%) !important;
  left: 0%;
  width: 100%;
  transition: left 0.35s;
}

.sidenav:not(.show) {
  left: -100%;
}
```

Now you have it. A good looking Sidenav. It wasn't hard. I did added a couple or more things to make it look nicer, a padding, and a background color, the same from the parent.


```css
.sidenav {
  position: absolute;
  top: 100%;
  height: calc(100vh - 100%) !important;
  left: 0%;
  width: 100%;
  transition: left 0.35s;
  padding: 2rem;
  background-color: inherit;
}

.sidenav:not(.show) {
  left: -100%;
}
```

Now, set a bigger screen in the DevTools device list, like an iPad.

> What? You broke my app.

Ok, first I didn't say anything about using a real app. Second,

# Fixing the big screen

The best you can do is to design to little screens, and latter fix it for the bigger ones. But this really seems to be mees up. What Bootstrap does, and what we will do, is wrap that class inside a media query. You can do what I did first, and just use the same media query that you are using for the `.navbar-expanded-{media query}`.

```css
@include media-breakpoint-down(sm) {
  .sidenav {
    position: absolute;
    top: 100%;
    height: calc(100vh - 100%) !important;
    width: 100%;
    left: 0%;
    transition: left 0.35s;
    padding: 2rem;
    background-color: inherit;
  }

  .sidenav:not(.show) {
    left: -100%;
  }
}
```
This have one disadvantage, now to modify the breakpoint you'll to adjust the `.navbar-expand-*` class, and also the breakpoint in the function. The advantage is that you don't need Bootstrap source files, and if you are doing something quickly, then this maybe your best option.

Or, you can use the same function that Bootstrap use. Notice that this is a private function, and it's currently not being exported. However, we can use the classic technique of `copy-paste`.

```scss
.navbar-expand {
  @each $breakpoint in map-keys($grid-breakpoints) {
    $next: breakpoint-next($breakpoint, $grid-breakpoints);
    $infix: breakpoint-infix($next, $grid-breakpoints);

    &#{$infix} {
      @include media-breakpoint-down($breakpoint) {
        .sidenav {
          position: absolute;
          top: 100%;
          height: calc(100vh - 100%) !important;
          width: 100%;
          left: 0%;
          transition: left 0.35s;
          padding: 2rem;
          background-color: inherit;
        }

        .sidenav:not(.show) {
          left: -100%;
        }
      }
    }
  }
}

```

This loop block can currently be found inside the `_navbar.scss` file, at line 140. What it does, is associate all the mediaqueries from `.navbar-expand-*` to the corresponding media query. With this you can use whatever media query you want, only updating that class.

# That's all folks!

Thanks for reading, I hope you find it interesting. I don't plan to publish this as a npm package because I think this is very opinionated. For instance, this example is using the `position: relative` default value of `.navbar` component, so if you want to apply another position as fixed or sticky, then you would have to update all the positional properties. Perhaps you want to use the light theme in your `.navbar`, but in the `.sidenav` you would to use the dark one. Again, you would need to modify according to your needs. However, I think this is a really simple way to start this, and adjust latter as you move.