Create Draggable Modal Using HTML, CSS, and JavaScript

Faraz

By Faraz - Last Updated:

Learn how to create a draggable modal using HTML, CSS, and JavaScript with this easy-to-follow guide. Perfect for web developers of all skill levels.


create-draggable-modal-using-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

A modal is a versatile UI component used to display content in a popup overlay, making it ideal for showing additional information or capturing user input without navigating away from the current page. Adding a draggable feature to a modal enhances user experience by allowing users to move the modal around the screen according to their preference. This can be especially useful in applications where the modal might obstruct important content or where users need to interact with multiple elements simultaneously.

In this guide, we'll walk you through creating a draggable modal using HTML, CSS, and JavaScript. You'll learn how to set up the basic structure, style the modal, and implement dragging functionality with straightforward JavaScript. This tutorial is designed for web developers at any skill level, whether you're a beginner just starting out or an experienced developer looking to refresh your skills. By the end of this guide, you'll have a fully functional draggable modal that you can easily integrate into your own projects.

Prerequisites

Before starting this tutorial, you should have the following:

  1. Basic Understanding of HTML: Know how to create and structure HTML elements.
  2. Fundamental CSS Knowledge: Familiarity with styling elements and basic layout techniques.
  3. Introductory JavaScript Skills: Ability to write simple JavaScript functions and handle events.
  4. A Code Editor: You will need a code editor such as Visual Studio Code or Sublime Text to write and save your code.

Source Code

Step 1 (HTML Code):

To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our modal.

Here’s a breakdown of each part:

1. Document Type and HTML Structure

<!DOCTYPE html>
<html lang="en">
  • <!DOCTYPE html>: Declares the document type and version of HTML.
  • <html lang="en">: The root element of the HTML document with the language set to English.

2. Head Section

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Draggable Modal using HTML, CSS, and JS</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap">
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
  • <meta charset="UTF-8">: Specifies the character encoding for the document.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Ensures the page is responsive on different devices.
  • <title>: Sets the title of the webpage that appears in the browser tab.
  • <link rel="stylesheet" href="...">: Links to external CSS files for styling:
    • Google Fonts for the Poppins font.
    • A local styles.css file for additional styles.
    • Font Awesome for icons.

3. Body Section

<body>
    <button id="openModalBtn">Open Modal</button>
  • <button id="openModalBtn">: A button to open the modal dialog.

4. Modal Structure

<div id="myModal" class="modal">
    <div class="modal-content">
        <header class="modal-header">
            <div>
                <h2>Modal Title</h2>
                <h3 class="modal-subtitle">Subtitle Here</h3>
            </div>
            <span class="close">×</span>
        </header>
        <div class="modal-body">
            <img src="https://www.codewithfaraz.com/tools/placeholder?size=400x200" alt="Placeholder Image" class="modal-image">
            <p>This is a minimalistic modal with a black and white theme...</p>
            <p>Additional text can be included here...</p>
        </div>
        <footer class="modal-footer">
            <div class="footer-text">
                <p>For more information, please contact us at <a href="mailto:[email protected]">[email protected]</a>.</p>
            </div>
            <div class="footer-icons">
                <i class="fas fa-phone-alt"></i>
                <i class="fas fa-envelope"></i>
                <i class="fas fa-info-circle"></i>
            </div>
        </footer>
    </div>
</div>
  • <div id="myModal" class="modal">: The container for the modal dialog.
    • <div class="modal-content">: The main content of the modal.
      • <header class="modal-header">: The header section of the modal, including:
        • <h2> and <h3>: Title and subtitle of the modal.
        • <span class="close">&times;</span>: A close button to exit the modal.
      • <div class="modal-body">: Contains the main content of the modal, including:
        • <img>: An image with placeholder content.
        • <p>: Paragraphs for additional text.
      • <footer class="modal-footer">: Footer of the modal, including:
        • <div class="footer-text">: Contact information.
        • <div class="footer-icons">: Icons for phone, email, and info (using Font Awesome).

5. Script Section

<script src="script.js"></script>
</body>
</html>
  • <script src="script.js"></script>: Links to an external JavaScript file that will handle the modal's functionality, such as opening and closing the modal.

Step 2 (CSS Code):

Next, we need to style our modal by adding CSS. This will give our modal an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension. Here’s a detailed breakdown:

1. General Body Styling

body {
  font-family: 'Poppins', Arial, sans-serif;
  background-color: #f4f4f4;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}
  • font-family: 'Poppins', Arial, sans-serif;: Sets the font to Poppins, with Arial and sans-serif as fallbacks.
  • background-color: #f4f4f4;: Light grey background color for the entire page.
  • display: flex; justify-content: center; align-items: center;: Uses Flexbox to center content both horizontally and vertically.
  • height: 100vh;: Makes the body’s height equal to the viewport height.
  • margin: 0;: Removes default margin around the body.

2. Button Styling

#openModalBtn {
  font-family: 'Poppins', Arial, sans-serif;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
  border-radius: 5px;
  border: 1px solid #000;
  background-color: #fff;
  color: #000;
  transition: background-color 0.3s, color 0.3s;
}

#openModalBtn:hover {
  color: #fff;
  background-color: #000;
}
  • #openModalBtn: Styles the button that opens the modal.
    • font-family, padding, font-size, cursor, border-radius, border, background-color, color: Sets font, spacing, appearance, and color.
    • transition: Smoothly animates background and text color changes.
  • :hover: Changes button color on hover for better interactivity.

3. Modal Styling

.modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.5);
  animation: fadeIn 0.5s;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
  • .modal: Styles the modal background.
    • display: none;: Hides the modal by default.
    • position: fixed;: Fixes the modal to the viewport.
    • z-index: 1;: Ensures the modal appears above other content.
    • background-color: rgba(0, 0, 0, 0.5);: Semi-transparent black background.
    • animation: fadeIn 0.5s;: Fades in the modal when it appears.

4. Modal Content Styling

.modal-content {
  background-color: #fff;
  margin: 10% auto;
  padding: 20px;
  border: 3px solid #000;
  width: 50%;
  max-width: 600px;
  border-radius: 8px;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
  transform: scale(0.9);
  transition: transform 0.3s ease-in-out;
  position: relative;
}

.modal-content.show {
  transform: scale(1);
}
  • .modal-content: Styles the inner content of the modal.
    • background-color, margin, padding, border, width, max-width, border-radius, box-shadow: Sets appearance, spacing, and size.
    • transform: scale(0.9);: Slightly scales down the content initially.
    • transition: transform 0.3s ease-in-out;: Smoothly scales the content up.
  • .modal-content.show: Restores the scale to normal when the modal is visible.

5. Modal Header Styling

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 2px solid #000;
  padding-bottom: 10px;
}

.modal-header h2 {
  margin: 0;
  font-size: 24px;
}

.modal-subtitle {
  font-size: 16px;
  color: #555;
}
  • .modal-header: Styles the header of the modal.
    • display: flex; justify-content: space-between; align-items: center;: Aligns header items in a row with space between.
    • border-bottom, padding-bottom: Adds a bottom border and padding.
  • h2: Styles the main title in the header.
  • .modal-subtitle: Styles the subtitle with a specific font size and color.

6. Close Button Styling

.close {
  color: #000;
  font-size: 24px;
  font-weight: bold;
  cursor: pointer;
}

.close:hover,
.close:focus {
  color: #555;
  text-decoration: none;
}
  • .close: Styles the close button in the header.
    • color, font-size, font-weight, cursor: Sets appearance and interactivity.
  • :hover and :focus: Changes color when hovered or focused.

7. Modal Body and Image Styling

.modal-body {
  margin: 20px 0;
}

.modal-body p {
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
}

.modal-image {
  width: 100%;
  height: auto;
  margin-bottom: 20px;
}
  • .modal-body: Adds margin around the body content.
  • p: Styles paragraphs with font size and line height.
  • .modal-image: Makes the image responsive and adds spacing below it.

8. Modal Footer Styling

.modal-footer {
  display: flex;
  flex-direction: column;
  border-top: 2px solid #000;
  padding-top: 10px;
  margin-top: 20px;
}

.footer-text {
  margin-bottom: 10px;
}

.footer-text p {
  margin: 0;
  font-size: 14px;
  color: #555;
}

.footer-text a {
  color: #000;
  text-decoration: none;
}

.footer-text a:hover {
  text-decoration: underline;
}

.footer-icons {
  display: flex;
  gap: 15px;
}

.footer-icons i {
  font-size: 20px;
  color: #000;
  cursor: pointer;
  transition: color 0.3s;
}

.footer-icons i:hover {
  color: #555;
}
  • .modal-footer: Styles the footer with a top border and padding.
    • display: flex; flex-direction: column;: Arranges footer content in a column.
  • .footer-text: Adds margin and styles text and links.
    • a: Styles links in the footer with color and text decoration.
  • .footer-icons: Styles icon section with spacing.
  • .footer-icons i: Styles individual icons with size, color, and transition effects.
body {
  font-family: 'Poppins',Arial, sans-serif;
  background-color: #f4f4f4;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}

#openModalBtn {
  font-family: 'Poppins',Arial, sans-serif;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
  border-radius: 5px;
  border: 1px solid #000;
  background-color: #fff;
  color: #000;
  transition: background-color 0.3s, color 0.3s;
}

#openModalBtn:hover {
  color: #fff;
  background-color: #000;
}

.modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.5);
  animation: fadeIn 0.5s;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.modal-content {
  background-color: #fff;
  margin: 10% auto;
  padding: 20px;
  border: 3px solid #000;
  width: 50%;
  max-width: 600px;
  border-radius: 8px;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
  transform: scale(0.9);
  transition: transform 0.3s ease-in-out;
  position: relative;
}

.modal-content.show {
  transform: scale(1);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 2px solid #000;
  padding-bottom: 10px;
}

.modal-header h2 {
  margin: 0;
  font-size: 24px;
}

.modal-subtitle {
  font-size: 16px;
  color: #555;
}

.close {
  color: #000;
  font-size: 24px;
  font-weight: bold;
  cursor: pointer;
}

.close:hover,
.close:focus {
  color: #555;
  text-decoration: none;
}

.modal-body {
  margin: 20px 0;
}

.modal-body p {
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
}

.modal-image {
  width: 100%;
  height: auto;
  margin-bottom: 20px;
}

.modal-footer {
  display: flex;
  flex-direction: column;
  border-top: 2px solid #000;
  padding-top: 10px;
  margin-top: 20px;
}

.footer-text {
  margin-bottom: 10px;
}

.footer-text p {
  margin: 0;
  font-size: 14px;
  color: #555;
}

.footer-text a {
  color: #000;
  text-decoration: none;
}

.footer-text a:hover {
  text-decoration: underline;
}

.footer-icons {
  display: flex;
  gap: 15px;
}

.footer-icons i {
  font-size: 20px;
  color: #000;
  cursor: pointer;
  transition: color 0.3s;
}

.footer-icons i:hover {
  color: #555;
} 

Step 3 (JavaScript Code):

Finally to enable dragging, we need to create a function in JavaScript. Here’s a breakdown of what each part does:

1. Event Listener for DOM Content Loaded

document.addEventListener('DOMContentLoaded', () => {
  // Code here runs when the DOM content is fully loaded
});
  • DOMContentLoaded: Ensures the script runs only after the entire HTML document has been fully loaded and parsed, but before other resources like images are fully loaded.

2. Selecting Elements

const modal = document.getElementById('myModal');
const openModalBtn = document.getElementById('openModalBtn');
const closeBtn = document.querySelector('.close');
const modalContent = document.querySelector('.modal-content');
  • modal: Selects the modal background element.
  • openModalBtn: Selects the button used to open the modal.
  • closeBtn: Selects the button to close the modal (inside the modal header).
  • modalContent: Selects the content area of the modal.

3. Opening the Modal

openModalBtn.addEventListener('click', () => {
    modal.style.display = 'block';
    setTimeout(() => {
        modalContent.classList.add('show');
    }, 10);
});
  • openModalBtn.addEventListener('click', ...): Attaches a click event listener to the button that opens the modal.
  • modal.style.display = 'block';: Shows the modal by setting its display property to block.
  • setTimeout(() => { ... }, 10);: Adds a short delay to ensure the modal is displayed before applying the show class.
  • modalContent.classList.add('show');: Adds the show class to the modal content, which scales it up using CSS.

4. Closing the Modal

closeBtn.addEventListener('click', () => {
    modalContent.classList.remove('show');
    setTimeout(() => {
        modal.style.display = 'none';
    }, 300);
});
  • closeBtn.addEventListener('click', ...): Attaches a click event listener to the close button inside the modal.
  • modalContent.classList.remove('show');: Removes the show class, which scales down the modal content.
  • setTimeout(() => { ... }, 300);: Adds a delay before hiding the modal to allow time for the scaling animation to complete.
  • modal.style.display = 'none';: Hides the modal by setting its display property to none.

5. Making the Modal Draggable

let isDragging = false;
let offsetX, offsetY;

modalContent.addEventListener('mousedown', (event) => {
    if (event.target !== closeBtn) {
        isDragging = true;
        offsetX = event.clientX - modalContent.getBoundingClientRect().left;
        offsetY = event.clientY - modalContent.getBoundingClientRect().top;
        modalContent.style.cursor = 'move';
    }
});

document.addEventListener('mousemove', (event) => {
    if (isDragging) {
        const x = event.clientX - offsetX;
        const y = event.clientY - offsetY;
        modalContent.style.position = 'absolute';
        modalContent.style.left = `${x}px`;
        modalContent.style.top = `${y}px`;
    }
});

document.addEventListener('mouseup', () => {
    isDragging = false;
    modalContent.style.cursor = 'default';
});
  • let isDragging = false;: Keeps track of whether the modal is being dragged.
  • let offsetX, offsetY;: Stores the offsets from the cursor to the modal’s top-left corner.

Drag Start

  • modalContent.addEventListener('mousedown', (event) => { ... });: Attaches a mousedown event listener to the modal content.
    • if (event.target !== closeBtn): Ensures dragging does not start if the click is on the close button.
    • isDragging = true;: Sets isDragging to true when starting to drag.
    • offsetX and offsetY: Calculate the cursor’s offset from the modal’s top-left corner.
    • modalContent.style.cursor = 'move';: Changes the cursor to a move icon during dragging.

Dragging

  • document.addEventListener('mousemove', (event) => { ... });: Attaches a mousemove event listener to the document.
    • if (isDragging): Checks if the modal is currently being dragged.
    • const x = event.clientX - offsetX;: Calculates the new horizontal position.
    • const y = event.clientY - offsetY;: Calculates the new vertical position.
    • modalContent.style.position = 'absolute';: Ensures the modal is positioned absolutely.
    • modalContent.style.left and modalContent.style.top: Updates the position of the modal.

Drag End

  • document.addEventListener('mouseup', () => { ... });: Attaches a mouseup event listener to the document.
    • isDragging = false;: Sets isDragging to false to stop dragging.
    • modalContent.style.cursor = 'default';: Resets the cursor to default.
document.addEventListener('DOMContentLoaded', () => {
  const modal = document.getElementById('myModal');
  const openModalBtn = document.getElementById('openModalBtn');
  const closeBtn = document.querySelector('.close');
  const modalContent = document.querySelector('.modal-content');

  openModalBtn.addEventListener('click', () => {
      modal.style.display = 'block';
      setTimeout(() => {
          modalContent.classList.add('show');
      }, 10);
  });

  closeBtn.addEventListener('click', () => {
      modalContent.classList.remove('show');
      setTimeout(() => {
          modal.style.display = 'none';
      }, 300);
  });

  let isDragging = false;
  let offsetX, offsetY;

  modalContent.addEventListener('mousedown', (event) => {
      if (event.target !== closeBtn) { 
          isDragging = true;
          offsetX = event.clientX - modalContent.getBoundingClientRect().left;
          offsetY = event.clientY - modalContent.getBoundingClientRect().top;
          modalContent.style.cursor = 'move';
      }
  });

  document.addEventListener('mousemove', (event) => {
      if (isDragging) {
          const x = event.clientX - offsetX;
          const y = event.clientY - offsetY;
          modalContent.style.position = 'absolute';
          modalContent.style.left = `${x}px`;
          modalContent.style.top = `${y}px`;
      }
  });

  document.addEventListener('mouseup', () => {
      isDragging = false;
      modalContent.style.cursor = 'default';
  });
});

Final Output:

create-draggable-modal-using-html-css-and-javascript.gif

Conclusion:

Creating a draggable modal with HTML, CSS, and JavaScript is a great way to enhance user experience on your website. By following this simple guide, you can add a modal that users can move around easily. This functionality can make your site more interactive and user-friendly. Feel free to customize the modal’s appearance and behavior to fit your needs.

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺