How to Add a Sliding Sidebar Menu to Your Site

Sep 19 2022 | By Taha Shashtari

Here's what we are going to build:

I'll explain only the relevant code below. If you want to see the full code, check the codepen above.

The HTML

<body>
  <div class="menu-sidebar">
    <div class="sidebar-content">
      <button class="close-menu-button">
        <!-- close button icon -->
      </button>
    </div>
  </div>
  <div class="overlay"></div>
  <div class="main-page">
    <div class="header">
      <button class="menu-button">
        <!-- menu icon -->
      </button>
    </div>
    <h1>Page Title</h1>
    <p>
      Lorem ipsum dolor sit amet...
    </p>
  </div>
</body>

This HTML consists of four main parts:

We have two states for this UI: idle and sidebar-open states. We specify which state is on by setting a class on the <body> – it can be any wrapper element, but I'm using body for this example. For this demo I used sidebar-open class for the sidebar-open state.

We will define the styling for each state using CSS, and when the sidebar-open class is toggled on body, the correct styling would be applied, which will be animated with transition.

Here's an example for defining styles for each state:

.main-page {
  // Styling for the main page when in idle state
}

body.sidebar-open .main-page {
  // Styling for the main page when in sidebar-open state
}

The CSS

/* Sidebar-open state for body */
body.sidebar-open {
  overflow: hidden;
}

/* Idle state for the sidebar */
.menu-sidebar {
  width: 500px;
  height: 100%;
  overflow: auto;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 2;
  transition: 0.5s ease translate;
  translate: -100% 0;
  will-change: transform;
}

/* Sidebar-open state for the sidebar */
body.sidebar-open .menu-sidebar {
  translate: 0 0;
}

/* Idle state for the main page */
.main-page {
  transition: 0.5s ease translate;
  will-change: transform;
}

/* Sidebar-open state for the main page */
body.sidebar-open .main-page {
  translate: 500px 0;
}

/* Idle state for the overlay */
.overlay {
  opacity: 0;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  transition: 0.5s ease opacity;
}

/* Sidebar-open state for the overlay */
body.sidebar-open .overlay {
  opacity: 1;
  pointer-events: all;
}

/* When on tablet-size screen, make the sidebar open in full width above the main page */
@media (max-width: 768px) {
  .menu-sidebar {
    width: 100%;
  }
  body.sidebar-open .main-page {
    translate: 0 0;
  }
}

Let's see how the elements will be in each state.

The sidebar (.menu-sidebar):

The main page (.main-page):

The overlay (.overlay):

The JavaScript

The last step to make this work is toggling sidebar-open class on body when the menu button, overlay, or close button is clicked.

const menuButton = document.querySelector('.menu-button')
const overlay = document.querySelector('.overlay')
const closeMenuButton = document.querySelector('.close-menu-button')

menuButton.addEventListener('click', toggleMenu)
overlay.addEventListener('click', toggleMenu)
closeMenuButton.addEventListener('click', toggleMenu)

function toggleMenu() {
  document.body.classList.toggle('sidebar-open')
}

Subscribe to get my latest posts