7

How to Add a Sliding Sidebar Menu to Your Site

 2 years ago
source link: https://tahazsh.com/blog/sidebar-menu-animation/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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:

  • The sidebar: .menu-sidebar
  • The main page section: .main-page
  • The button that opens the sidebar: .menu-button
  • And the overlay displayed on top of the main page when the sidebar is open: .overlay

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):

  • We don't want the sidebar to be part of the page flow, so we are positioning it with position: fixed.
  • To make it appear above the main page when open, we need to set its z-index to something bigger than .overlay and the main page. So we set it z-index: 2.
  • I've chosen its width to be 500px but you can choose any width you want.
  • In idle state, the sidebar should be positioned outside the viewport. Setting translate: -100% 0 will move it to the left by its full width.
  • For better performance, we will animate the sidebar using translate, and to make that even better, we need to promote the element to a new layer. That's what will-change does.
  • In sidebar-open state, the sidebar translate will be 0 0 which means it will move back to its original position, and with transition it will appear as animating to the right.

The main page (.main-page):

  • We don't need to do anything when in idle state. We just need to make sure it has transition and will-change for animation purposes.
  • But when in sidebar-open state, this element needs to move to the right by the same width as the sidebar, which is 500px in this case.

The overlay (.overlay):

  • It's a fixed element with full width and height to cover the whole screen. It also has a background with transparency to see the main page below it background: rgba(0, 0, 0, 0.5).
  • It should be hidden when in idle state. We are using opacity: 0 here and not display: none because we want to animate it with transition: 0.5s ease opacity.
  • An element with opacity: 0 still exists on the page but not seen. So clicking anything on the page would not work because you will be clicking on .overlay. To fix this, we set pointer-events: none, which disables all mouse and touch events on it.
  • When in sidebar-open state, we just need to show it and enable clicking on it (so it closes the sidebar when you click on it). To do this, we set opacity: 1 and pointer-events: all .

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')
}

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK