How to make a Draggable Bottom Sheet Modal using CSS & JS

bottom -modal

Introduction

In this comprehensive blog post, we will embark on a journey to create a draggable bottom sheet modal using HTML, CSS, and JavaScript. This interactive UI component not only provides an elegant and user-friendly experience but also showcases the seamless integration of frontend technologies. Let’s dive into the intricacies of each section of the code to unveil the magic behind this draggable bottom sheet modal.

HTML Structure

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8" />
    <title>Draggable Bottom Sheet Modal</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <button class="show-modal-btn">Show Bottom Sheet</button>
    <div class="bottom-sheet-container">
      <div class="sheet-overlay"></div>
      <div class="sheet-content">
        <div class="sheet-header">
          <div class="drag-icon"><span></span></div>
        </div>
        <div class="sheet-body">
          <h2>Draggable Bottom Sheet Modal</h2>
          <!-- Your content goes here -->
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi
            distinctio illo temporibus consectetur quos veritatis tempore
            incidunt dolorem alias aperiam et sapiente ex eaque natus, nesciunt,
            itaque a ipsam numquam rerum dolores voluptatum quia deleniti ullam
            vero! Quae, officiis esse sunt vitae similique cum vel corporis
            assumenda, nesciunt, repellat dignissimos?
          </p>
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi
            distinctio illo temporibus consectetur quos veritatis tempore
            incidunt dolorem alias aperiam et sapiente ex eaque natus, nesciunt,
            itaque a ipsam numquam rerum dolores voluptatum quia deleniti ullam
            vero! Quae, officiis esse sunt vitae similique cum vel corporis
            assumenda, nesciunt, repellat dignissimos?
          </p>
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi
            distinctio illo temporibus consectetur quos veritatis tempore
            incidunt dolorem alias aperiam et sapiente ex eaque natus, nesciunt,
            itaque a ipsam numquam rerum dolores voluptatum quia deleniti ullam
            vero! Quae, officiis esse sunt vitae similique cum vel corporis
            assumenda, nesciunt, repellat dignissimos?
          </p>
        </div>
      </div>
    </div>
  </body>
</html>
HTML

HTML Breakdown:

  1. Show Modal Button: A button with the class show-modal-btn triggers the display of the bottom sheet.
  2. Bottom Sheet Container: The main container for the bottom sheet includes an overlay and the sheet content.
  3. Sheet Overlay: An overlay covering the entire screen prevents interaction with the underlying content when the bottom sheet is active.
  4. Sheet Content: The actual content of the bottom sheet, consisting of a header, body, and a drag icon.
  5. Sheet Header: The header section, where you can customize the appearance or add additional elements.
  6. Drag Icon: An icon that users can grab to drag the bottom sheet.

CSS Styling

@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background-color: #1e1c27;
  color: white;
}
.show-modal-btn {
  outline: none;
  border: none;
  cursor: pointer;
  color: #fff;
  border-radius: 6px;
  font-size: 1.2rem;
  padding: 15px 22px;
  background: #4a98f7;
  transition: 0.3s ease;
  box-shadow: 0 10px 18px rgba(52, 87, 220, 0.18);
}
.show-modal-btn:hover {
  background: #2382f6;
}
.bottom-sheet-container {
  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-container.show {
  opacity: 1;
  pointer-events: auto;
}
.bottom-sheet-container .sheet-overlay {
  position: fixed;
  top: 0;
  left: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  opacity: 0.2;
  background: #000;
}
.bottom-sheet-container .sheet-content {
  width: 100%;
  position: relative;
  background: #fff;
  max-height: 100vh;
  height: 50vh;
  max-width: 1150px;
  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;
  color: black;
}
.bottom-sheet-container.show .sheet-content {
  transform: translateY(0%);
}
.bottom-sheet-container.dragging .sheet-content {
  transition: none;
}
.bottom-sheet-container.fullscreen .sheet-content {
  border-radius: 0;
  overflow-y: hidden;
}
.bottom-sheet-container .sheet-header {
  display: flex;
  justify-content: center;
}
.sheet-header .drag-icon {
  cursor: grab;
  user-select: none;
  padding: 15px;
  margin-top: -15px;
}
.sheet-header .drag-icon span {
  height: 4px;
  width: 40px;
  display: block;
  background: #c7d0e1;
  border-radius: 50px;
}
.bottom-sheet-container .sheet-body {
  height: 100%;
  overflow-y: auto;
  padding: 15px 0 40px;
  scrollbar-width: none;
}
.bottom-sheet-container .sheet-body::-webkit-scrollbar {
  width: 0;
}
.sheet-body h2 {
  font-size: 1.8rem;
}
.sheet-body p {
  margin-top: 20px;
  font-size: 1.05rem;
}
CSS

CSS Highlights:

  1. Global Styles: Sets global styles, including the Poppins font import, box-sizing, and font-family.
  2. Body Styles: Defines the styling for the body, setting the display flex, background color, and text color.
  3. Button Styles: Styles for the button that triggers the bottom sheet, including color, padding, and transitions.
  4. Bottom Sheet Container Styles: Specifies the initial styles for the bottom sheet container, including position, opacity, and transitions.
  5. Sheet Overlay Styles: Styles for the overlay that covers the entire screen.
  6. Sheet Content Styles: Defines the appearance of the sheet content, including width, height, padding, and transitions.
  7. Sheet Header Styles: Styles for the header section, which can be customized based on design preferences.
  8. Drag Icon Styles: Styles for the grabbable drag icon within the header.

JavaScript Functionality

const showModalButton = document.querySelector(".show-modal-btn");
const bottomSheetContainer = document.querySelector(
  ".bottom-sheet-container"
);
const sheetOverlay = bottomSheetContainer.querySelector(".sheet-overlay");
const sheetContent = bottomSheetContainer.querySelector(".sheet-content");
const dragIcon = bottomSheetContainer.querySelector(".drag-icon");

let isDragging = false,
  startY,
  startHeight;

const showBottomSheet = () => {
  bottomSheetContainer.classList.add("show");
  document.body.style.overflowY = "hidden";
  updateSheetHeight(50);
};

const updateSheetHeight = (height) => {
  sheetContent.style.height = `${height}vh`;
  bottomSheetContainer.classList.toggle("fullscreen", height === 100);
};

const hideBottomSheet = () => {
  bottomSheetContainer.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);
  bottomSheetContainer.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;
  bottomSheetContainer.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);
showModalButton.addEventListener("click", showBottomSheet);
JavaScript

JavaScript Breakdown:

  1. Function Declarations: Functions like showBottomSheet, updateSheetHeight, and hideBottomSheet are defined for controlling the bottom sheet’s behavior.
  2. Event Listeners: Event listeners are added for mouse and touch events to handle dragging and interaction.
  3. Drag Handling: The dragStart, dragging, and dragStop functions manage the dragging functionality of the bottom sheet.
  4. Show and Hide: Functions to show and hide the bottom sheet are implemented.
  5. Event Binding: Event listeners are bound to relevant elements such as the drag icon, overlay, and the button that triggers the bottom sheet.

Conclusion

In this blog post, we’ve uncovered the intricacies of creating a draggable bottom sheet modal using HTML, CSS, and JavaScript. This UI component enhances user interaction and provides a sleek and modern design to your web application. Feel free to customize and integrate this code into your projects, tailoring it to fit your specific design and functionality requirements.

Explore the possibilities, experiment with variations, and let your creativity shape a delightful user experience.

Happy coding!

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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