How to Build Modern Javascript Sliding Menu ➡️ [like Facebook]

In this tutorial I will share how I built Javascript sliding menu with CSS and Javascript. I was inspired by multi level dropdown menu at Facebook website.

This widget has an advantage – compactness and adds points to your UX.

As a UI designer I decided to use a Glassmorphism UI style for this project.

So, let’s go and see the project in action below ⬇️

javascript sliding menu
javascript sliding menu

Project: Javascript Sliding Menu

// javascript sliding menu

See the Pen Sliding Menu Javascript by jsSecrets (@jssecrets) on CodePen.

Basic Working Principle

What is Multi Level Menu in a nutshell?

Multi level menu is another design pattern that helps to display content in a compact way. Other examples are Accordion and Tabs. Also, iOS “Settings” menu is built like a multi level one.

Usually there a main screen with links to sections. For instance iOS has the following section links:

1️⃣ Wi-Fi

2️⃣ Bluetooth

3️⃣ Cellular

Inside each section there is a corresponding content. Which also may contain links to sub-sections.

This design pattern saves a lot of space and improves UX.

sliding menu js
sliding menu js

Working Principle

Simplest Working Version (SWV)

We have some number of screens. One of them is the main one, which is visible at the start. Other screens are hidden.

In HTML representation screen could be a <div> or in my case i use <ul>. All screens are wrapped with a parent <div>.

In CSS each screen is set to width: 100%. And parent <div> is set to overflow: hidden. These two facts together make only screen visible at the time. The visible screen is display:block, hidden ones are display:hidden. We can also set CSS visibility class to use in JS.

With the help of JS we show clicked section and hide the current.

Core concept

// javascript sliding menu

Let’s continue with core concept of how JS sliding multi level menu works.

1️⃣ HTML

// javascript sliding menu

The main parent element <.menu> contains three child elements. Let’s call them screens. We have one main screen and two descendant ones. Each screen contains items. And second level screens also have a “Back” button.

The a schematic markup looks like this:

<.menu>
   <.screen>
     <.back>
     <.item>...</.item>
     <.item>...</.item>
     <.item>...</.item>
     ...
   </.screen>

   <.screen>
      ...
   </.screen>

   ...
</.menu>

2️⃣ CSS

// javascript sliding menu

The main parent element <.menu> has display: flex in row direction. Static width value and overflow: hidden.

Each of the descendant screens is width: 100% and display: none.

And the screen that is currently active has a class of .show.

 .show {
     display: block;
  }

A combination of those facts means that in any moment of time only one screen is visible.

It resembles slider’s functionality.

3️⃣ Javascript

// javascript sliding menu

As in many cases with UI elements Javascript acts as “manager”.

In this case almost 100% of the work is adding and removing classes.

Let me show and explain the piece of code:

const goToHelp = () => {
  removeClass('show', mainMenu);
  addClass('show', helpMenu);
  addClass('slideLeftToZero', helpMenu);
  removeClassDelayed('slideLeftToZero', helpMenu, 500);
};

goToHelp() function navigates to the “Help” menu. And to do that, it removes class .show from the “Main menu” and add class .show to “Help menu”.

Even these two commands will do the work.

To create a sliding menu effect we need CSS animation.

That’s why the .slideLeftToZero class (simple CSS animation) is added to “Help menu”.

And the after .5s (random manual value) I remove the .slideLeftToZero class from “Help menu”. Because if class remains on the element we won’t see animation the second time.

Code explanation

// javascript sliding menu

If you have understood the core concept of how the Javascript sliding menu was built, the code will be easy to grasp.

HTML

// javascript sliding menu

I decided not to add <SVG> code for icons as theirs it takes too much space. I’ve just descriptively commented them.

But you can get all the HTML with <SVG> from Codepen or Github below in the “Resources”.

<body>

 <!-- wrapper -->
<div class="menu">

<!-- menu screen #1 -->
  <ul class="main-menu show">
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>
        <span>Give Feedback</span>
      </div>
    </li>
    <li class="item">
      <div id="setting-privacy" class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Settings & Privacy</span>
        <svg>
            <!-- navigate forward icon -->
        </svg>
      </div>
    </li>
    <li class="item">
      <div id="help-support" class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Help & Support</span>
        <svg>
            <!-- navigate forward icon -->
        </svg>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Log Out</span>
      </div>
    </li>
  </ul>


<!-- menu screen #2 -->
  <ul class="settings-menu">
    <li id="back-btn-from-settings" class="item back">
      <div class="item-name">
        <svg>
            <!-- navigate back icon -->
        </svg>

        <span>Back</span>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Activity Log</span>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>
        <span>Preferences</span>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Language</span>
      </div>
    </li>
  </ul>


<!-- menu screen #3 -->
  <ul class="help-menu">
    <li id="back-btn-from-help" class="item back">
      <div class="item-name">
        <svg>
            <!-- navigate back icon -->
        </svg>

        <span>Back</span>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Help Center</span>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>

        <span>Support</span>
      </div>
    </li>
    <li class="item">
      <div class="item-name">
        <svg>
            <!-- icon -->
        </svg>
        <span>Report a Problem</span>
      </div>
    </li>
  </ul>
</div>

</body>

CSS

// javascript sliding menu

/* basic reset */
*,
::before,::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Urbanist", sans-serif;
}

ul {
  list-style: none;
}

body {
  height: 100vh;
  background: radial-gradient(circle, rgb(255, 255, 255) 70%, rgb(243, 243, 243) 100%);
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.menu {
  width: 300px;
  padding: 20px;
  display: flex;
  border-radius: 9px;
  box-shadow: 0 10px 25px rgba(124, 130, 141, 0.2);

/*overflow is hidden*/
  overflow: hidden;


/* Glassmorphism effect */
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(4.5px);
  -webkit-backdrop-filter: blur(4.5px);
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.menu .main-menu,
.menu .settings-menu,
.menu .help-menu {
  width: 100%;
  height: 100%;

/* default display value */
  display: none;

  border-radius: 9px;
  transition: all 0.3s linear;
}
.menu .main-menu.show,
.menu .settings-menu.show,
.menu .help-menu.show {


/* when screen is shown - display value */
  display: block;
}


/* decoration styles */
.menu .main-menu .item:nth-of-type(1):hover {
  background: #7b42d1;
  box-shadow: 0 10px 25px rgba(123, 66, 209, 0.4);
}
.menu .main-menu .item:nth-of-type(2):hover {
  background: #f7ce51;
  box-shadow: 0 10px 25px rgba(245, 205, 81, 0.4);
}
.menu .main-menu .item:nth-of-type(3):hover {
  background: #5bc5fa;
  box-shadow: 0 10px 25px rgba(42, 179, 248, 0.4);
}
.menu .main-menu .item:nth-of-type(4):hover {
  background: #eb3dae;
  box-shadow: 0 10px 25px rgba(222, 23, 152, 0.4);
}
.menu .settings-menu .item:hover {
  background: #f7ce51;
  box-shadow: 0 10px 25px rgba(245, 205, 81, 0.4);
}
.menu .settings-menu .item.back {
  background: transparent;
  box-shadow: none;
  opacity: 0.7;
}
.menu .settings-menu .item.back:hover {
  opacity: 1;
}
.menu .help-menu .item:hover {
  background: #5bc5fa;
  box-shadow: 0 10px 25px rgba(42, 179, 248, 0.4);
}
.menu .help-menu .item.back {
  background: transparent;
  box-shadow: none;
  opacity: 0.7;
}
.menu .help-menu .item.back:hover {
  opacity: 1;
}

.item {
  padding: 16px;
  border-radius: 9px;
  background: white;
  box-shadow: 0 10px 25px rgba(124, 130, 141, 0.2);
  cursor: pointer;
  position: relative;
  transition: all 0.3s ease;
}
.item:not(.back):hover span {
  color: white;
  transition: all 0.2s ease-out;
}
.item:not(.back):hover path {
  fill: white;
  transition: all 0.2s ease-out;
}
.item span {
  font-size: 20px;
}
.item.back {
  box-shadow: none;
}
.item.back > * {
  opacity: 0.5;
}
.item.back .item-icon {
  opacity: 0.5;
}
.item:not(:last-of-type) {
  margin-bottom: 16px;
}
.item-name {
  font-size: 20px;
  color: #292d34;
}
.item-icon {
  vertical-align: sub;
  margin-right: 10px;
}
.item-icon.back {
  position: relative;
  top: -2px;
}
.item .chevron-icon {
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translate(0, -50%);
}


/* animations */

@keyframes slideLeftToZero {
  from {
    opacity: 0;
    transform: translateX(100%);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
@keyframes slideRightToZero {
  from {
    opacity: 0;
    transform: translateX(-100%);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
.slideLeftToZero {
  animation: slideLeftToZero 0.5s ease-out forwards;
}

.slideRightToZero {
  animation: slideRightToZero 0.5s ease-out forwards;
}
javascript sliding menu
javascript sliding menu

Javascript

// javascript sliding menu

// Variables
const mainMenu = document.querySelector('.main-menu');
const settingsMenu = document.querySelector('.settings-menu');
const helpMenu = document.querySelector('.help-menu');

const settingsPrivacyBtn = document.querySelector('#setting-privacy');
const helpSupportBtn = document.querySelector('#help-support');
const backBtnFromSettings = document.querySelector('#back-btn-from-settings');
const backBtnFromHelp = document.querySelector('#back-btn-from-help');

// Functions

// utililty functions
// I decided to wrap into functions
// adding, removing class and removing class on delay
// as they are used more than once

// it is a good practice of DRY code
// DRY = Don't Repeat Yourself

const addClass = (className, element) => {
  element.classList.add(className);
};
const removeClass = (className, element) => {
  element.classList.remove(className);
};
const removeClassDelayed = (className, element, delay) => {
  setTimeout(() => {
    removeClass(className, element);
  }, delay);
};


// following functions are very similar

// as you can see
// we remove class .show from the active screen
// and add class .show to one we would like to see

// then we add animation class
// .slideLeftToZero or .slideRightToZero
// it depends on a slide direction
// to see the sliding effect

// and after half of the second
// the animation class is removed 
// so the animation could be repeated in the future

const goToSettings = () => {
  removeClass('show', mainMenu);
  addClass('show', settingsMenu);
  addClass('slideLeftToZero', settingsMenu);
  removeClassDelayed('slideLeftToZero', settingsMenu, 500);
};

const goToHelp = () => {
  removeClass('show', mainMenu);
  addClass('show', helpMenu);
  addClass('slideLeftToZero', helpMenu);
  removeClassDelayed('slideLeftToZero', helpMenu, 500);
};

const goFromSettings = () => {
  removeClass('show', settingsMenu);
  addClass('show', mainMenu);
  addClass('slideRightToZero', mainMenu);
  removeClassDelayed('slideRightToZero', mainMenu, 500);
};

const goFromHelp = () => {
  removeClass('show', helpMenu);
  addClass('show', mainMenu);
  addClass('slideRightToZero', mainMenu);
  removeClassDelayed('slideRightToZero', mainMenu, 500);
};

// Event Listeners
settingsPrivacyBtn.addEventListener('click', goToSettings);
helpSupportBtn.addEventListener('click', goToHelp);
backBtnFromSettings.addEventListener('click', goFromSettings);
backBtnFromHelp.addEventListener('click', goFromHelp);

Project Ideas

// javascript sliding menu

1️⃣ Create a sliding multi level menu with three or more nested levels. You can play with iPhone’s “Settings” menu and see yourself.

2️⃣ Add this JS sliding menu to a navbar as a dropdown item. You can see a live example at Facebook website.

3️⃣ Think on a different style and direction of animation. Now it comes from left and right, try from top and bottom or even from front and behind 🙂

javascript sliding menu
javascript sliding menu

What to do next?

You can check out my similar projects:

1️⃣ Javascript Sliding Tabs

2️⃣ Javascript Accordion

Note
If you have some Javascript project in mind that you want me to explain, please write it in the comments.

Resources

// javascript sliding menu

1️⃣ jssecrets.com

2️⃣ Online illustrations by Storyset

3️⃣ Technology illustrations by Storyset

4️⃣ Web illustrations by Storyset

5️⃣ Javascript Sliding Menu Codepen

Ilyas Seisov

Ilyas Seisov

UI/Web designer and Javascript developer with Master's degree in Computer Science. He helps businesses transform ideas into reality with the power of design and code. Ilyas creates modern, aesthetic web applications and reads minds in a free time.

Leave a Reply

Your email address will not be published. Required fields are marked *