iOS Style Bottom Sheet Modal With JavaScript

Category: Javascript , Modal & Popup | October 21, 2024
Authorali-jabbari
Last UpdateOctober 21, 2024
LicenseMIT
Views703 views
iOS Style Bottom Sheet Modal With JavaScript

This bottom sheet modal provides a simple, mobile-friendly way to present content that slides up from the bottom of the screen, similar to iOS’s bottom sheet.

It supports both drag events on desktop and swipe gestures on mobile.  Users can drag it up to reveal more content or drag it down to close.

This allows developers to present secondary information, forms, or options in a familiar, easy-to-use format that doesn’t require users to navigate away from their current context.

How to use it:

1. Add the HTML structure for the bottom sheet modal, including the overlay, content area, header with drag icon, and body for your custom content.

<div class="bottom-sheet">
  <div class="sheet-overlay"></div>
  <div class="content">
    <div class="header">
      <div class="drag-icon"><span></span></div>
    </div>
    <div class="body">
      <h2>Moda Title</h2>
      <p>Modal Content</p>
    </div>
  </div>
</div>

2. The CSS below provides the basic styling. You can customize it to match your project’s design.

.bottom-sheet {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  opacity: 0;
  pointer-events: none;
  align-items: center;
  flex-direction: column;
  justify-content: flex-end;
  transition: 0.1s linear;
}
.bottom-sheet.show {
  opacity: 1;
  pointer-events: auto;
}
.bottom-sheet .sheet-overlay {
  position: fixed;
  top: 0;
  left: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  opacity: 0.2;
  background: #000;
}
.bottom-sheet .content {
  width: 100%;
  position: relative;
  background: #fff;
  max-height: 100vh;
  height: 50vh;
  padding: 25px 30px;
  transform: translateY(100%);
  border-radius: 12px 12px 0 0;
  box-shadow: 0 10px 20px rgba(0,0,0,0.03);
  transition: 0.3s ease;
}
.bottom-sheet.show .content{
  transform: translateY(0%);
}
.bottom-sheet.dragging .content {
  transition: none;
}
.bottom-sheet.fullscreen .content {
  border-radius: 0;
  overflow-y: hidden;
}
.bottom-sheet .header {
  display: flex;
  justify-content: center;
}
.header .drag-icon {
  cursor: grab;
  user-select: none;
  padding: 15px;
  margin-top: -15px;
}
.header .drag-icon span {
  height: 4px;
  width: 40px;
  display: block;
  background: #C7D0E1;
  border-radius: 50px;
}
.bottom-sheet .body {
  height: 100%;
  overflow-y: auto;
  padding: 15px 0 40px;
  scrollbar-width: none;
}
.bottom-sheet .body::-webkit-scrollbar {
  width: 0;
}

3. Create a button to trigger the modal:

<button class="show-modal">Launch The Modal</button>

4. Implement the JavaScript code to control the sheet’s behavior:

  • Select necessary DOM elements
  • Define functions for showing, hiding, and updating the sheet’s height
  • Implement drag functionality, including start, drag, and stop handlers
  • Add event listeners for user interactions
const showModalBtn = document.querySelector(".show-modal");
const bottomSheet = document.querySelector(".bottom-sheet");
const sheetOverlay = bottomSheet.querySelector(".sheet-overlay");
const sheetContent = bottomSheet.querySelector(".content");
const dragIcon = bottomSheet.querySelector(".drag-icon");
let isDragging = false, startY, startHeight;
const showBottomSheet = () => {
    bottomSheet.classList.add("show");
    document.body.style.overflowY = "hidden";
    updateSheetHeight(50);
}
const updateSheetHeight = (height) => {
    sheetContent.style.height = `${height}vh`;
    bottomSheet.classList.toggle("fullscreen", height === 100);
}
const hideBottomSheet = () => {
    bottomSheet.classList.remove("show");
    document.body.style.overflowY = "auto";
}
const dragStart = (e) => {
    isDragging = true;
    startY = e.pageY || e.touches?.[0].pageY;
    startHeight = parseInt(sheetContent.style.height);
    bottomSheet.classList.add("dragging");
}
const dragging = (e) => {
    if(!isDragging) return;
    const delta = startY - (e.pageY || e.touches?.[0].pageY);
    const newHeight = startHeight + delta / window.innerHeight * 100;
    updateSheetHeight(newHeight);
}
const dragStop = () => {
    isDragging = false;
    bottomSheet.classList.remove("dragging");
    const sheetHeight = parseInt(sheetContent.style.height);
    sheetHeight < 25 ? hideBottomSheet() : sheetHeight > 75 ? updateSheetHeight(100) : updateSheetHeight(50);
}
dragIcon.addEventListener("mousedown", dragStart);
document.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", dragStop);
dragIcon.addEventListener("touchstart", dragStart);
document.addEventListener("touchmove", dragging);
document.addEventListener("touchend", dragStop);
sheetOverlay.addEventListener("click", hideBottomSheet);
showModalBtn.addEventListener("click", showBottomSheet);

You Might Be Interested In:


Leave a Reply