Create Modal Box using JavaScript, HTML, and CSS

In this tutorial, you'll learn how to create a versatile Modal Box, a staple in modern web design for displaying dialogues, forms, or information without leaving the current page. Using vanilla JavaScript, HTML, and CSS, we'll build a responsive and accessible modal that can be adapted for various applications.

Project Setup

Workspace Preparation: Create a folder named modal to hold your project files. This will keep your development environment organized.

File Structure: Inside your project folder, create three files:
  • index.html: The markup for your modal and triggering button.
  • style.css: Styles to make your modal visually appealing.
  • script.js: JavaScript is used to add dynamic behavior to the model.

Development Steps

1. HTML Structure (index.html)

  • Begin with the basic HTML5 template.
  • Add a button within a header element that users will click to open the modal.
  • Define a div with the class modal-overlay, which contains your modal dialog (modal-container). When active, this overlay will cover the entire viewport.
  • Include a close button inside the modal for accessibility.
Let's open the index.html and add the following code to it:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Modal</title>
    <!-- font-awesome -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"
    />
    <!-- styles -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <!-- hero -->
    <header class="hero">
      <div class="banner">
        <h1>modal project</h1>
        <button class="btn modal-btn">
          open modal
        </button>
      </div>
    </header>
    <!-- modal -->
    <div class="modal-overlay">
      <div class="modal-container">
        <h3>modal content</h3>
        <button class="close-btn"><i class="fas fa-times"></i></button>
      </div>
    </div>
    <!-- javascript -->
    <script src="script.js"></script>
  </body>
</html>

2. Styling (style.css) 

Let's open style.css file, and add the following code to it:
/*
===============
Fonts
===============
*/
@import url("https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap");

/*
===============
Variables
===============
*/

:root {
  /* dark shades of primary color*/
  --clr-primary-1: hsl(205, 86%, 17%);
  --clr-primary-2: hsl(205, 77%, 27%);
  --clr-primary-3: hsl(205, 72%, 37%);
  --clr-primary-4: hsl(205, 63%, 48%);
  /* primary/main color */
  --clr-primary-5: #49a6e9;
  /* --clr-primary-5: rgb(73, 166, 233); */
  /* lighter shades of primary color */
  --clr-primary-6: hsl(205, 89%, 70%);
  --clr-primary-7: hsl(205, 90%, 76%);
  --clr-primary-8: hsl(205, 86%, 81%);
  --clr-primary-9: hsl(205, 90%, 88%);
  --clr-primary-10: hsl(205, 100%, 96%);
  /* darkest grey - used for headings */
  --clr-grey-1: hsl(209, 61%, 16%);
  --clr-grey-2: hsl(211, 39%, 23%);
  --clr-grey-3: hsl(209, 34%, 30%);
  --clr-grey-4: hsl(209, 28%, 39%);
  /* grey used for paragraphs */
  --clr-grey-5: hsl(210, 22%, 49%);
  --clr-grey-6: hsl(209, 23%, 60%);
  --clr-grey-7: hsl(211, 27%, 70%);
  --clr-grey-8: hsl(210, 31%, 80%);
  --clr-grey-9: hsl(212, 33%, 89%);
  --clr-grey-10: hsl(210, 36%, 96%);
  --clr-white: #fff;
  --clr-red-dark: hsl(360, 67%, 44%);
  --clr-red-light: hsl(360, 71%, 66%);
  --clr-green-dark: hsl(125, 67%, 44%);
  --clr-green-light: hsl(125, 71%, 66%);
  --clr-black: #222;
  --ff-primary: "Roboto", sans-serif;
  --ff-secondary: "Open Sans", sans-serif;
  --transition: all 0.3s linear;
  --spacing: 0.25rem;
  --radius: 0.5rem;
  --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
  --max-width: 1170px;
  --fixed-width: 620px;
}
/*
===============
Global Styles
===============
*/

*,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  font-family: var(--ff-secondary);
  background: var(--clr-grey-10);
  color: var(--clr-grey-1);
  line-height: 1.5;
  font-size: 0.875rem;
}
ul {
  list-style-type: none;
}
a {
  text-decoration: none;
}
img:not(.logo) {
  width: 100%;
}
img {
  display: block;
}

h1,
h2,
h3,
h4 {
  letter-spacing: var(--spacing);
  text-transform: capitalize;
  line-height: 1.25;
  margin-bottom: 0.75rem;
  font-family: var(--ff-primary);
}
h1 {
  font-size: 3rem;
}
h2 {
  font-size: 2rem;
}
h3 {
  font-size: 1.25rem;
}
h4 {
  font-size: 0.875rem;
}
p {
  margin-bottom: 1.25rem;
  color: var(--clr-grey-5);
}
@media screen and (min-width: 800px) {
  h1 {
    font-size: 4rem;
  }
  h2 {
    font-size: 2.5rem;
  }
  h3 {
    font-size: 1.75rem;
  }
  h4 {
    font-size: 1rem;
  }
  body {
    font-size: 1rem;
  }
  h1,
  h2,
  h3,
  h4 {
    line-height: 1;
  }
}
/*  global classes */

.btn {
  text-transform: uppercase;
  background: transparent;
  color: var(--clr-black);
  padding: 0.375rem 0.75rem;
  letter-spacing: var(--spacing);
  display: inline-block;
  transition: var(--transition);
  font-size: 0.875rem;
  border: 2px solid var(--clr-black);
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  border-radius: var(--radius);
}
.btn:hover {
  color: var(--clr-white);
  background: var(--clr-black);
}
/* section */
.section {
  padding: 5rem 0;
}

.section-center {
  width: 90vw;
  margin: 0 auto;
  max-width: 1170px;
}
@media screen and (min-width: 992px) {
  .section-center {
    width: 95vw;
  }
}
main {
  min-height: 100vh;
  display: grid;
  place-items: center;
}
/*
===============
Modal
===============
*/
.hero {
  min-height: 100vh;
  background: url("./hero.jpeg") center/cover no-repeat;
  display: grid;
  place-items: center;
}
.banner {
  background: var(--clr-white);
  padding: 4rem 0;
  border-radius: var(--radius);
  box-shadow: var(--light-shadow);
  text-align: center;
  width: 90vw;
  max-width: var(--fixed-width);
}
.modal-btn {
  margin-top: 2rem;
  background: var(--clr-primary-5);
  border-color: var(--clr-primary-5);
  color: var(--clr-white);
}
.modal-btn:hover {
  background: transparent;
  color: var(--clr-primary-5);
}
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(73, 166, 233, 0.5);
  display: grid;
  place-items: center;
  transition: var(--transition);
  visibility: hidden;
  z-index: -10;
}
/* OPEN/CLOSE MODAL */
.open-modal {
  visibility: visible;
  z-index: 10;
}
.modal-container {
  background: var(--clr-white);
  border-radius: var(--radius);
  width: 90vw;
  height: 30vh;
  max-width: var(--fixed-width);
  text-align: center;
  display: grid;
  place-items: center;
  position: relative;
}
.close-btn {
  position: absolute;
  top: 1rem;
  right: 1rem;
  font-size: 2rem;
  background: transparent;
  border-color: transparent;
  color: var(--clr-red-dark);
  cursor: pointer;
  transition: var(--transition);
}
.close-btn:hover {
  color: var(--clr-red-light);
  transform: scale(1.3);
}
Reset default browser styling to ensure consistency across different browsers. 

Use CSS variables to define your color scheme and other reusable values, making future changes or theming easier. 

Style the modal overlay to be full-screen with a semi-transparent background, hidden by default. 

Design the modal container with responsive width, centered positioning, and an appealing box-shadow for depth. 

Add hover and focus styles for interactive elements to improve usability.

3. JavaScript Functionality (script.js) 

Let's open the JavaScript file named script.js and add the following JavaScript code to it:
// select modal-btn,modal-overlay,close-btn
// listen for click events on modal-btn and close-btn
// when user clicks modal-btn add .open-modal to modal-overlay
// when user clicks close-btn remove .open-modal from modal-overlay

const modalBtn = document.querySelector(".modal-btn");
const modal = document.querySelector(".modal-overlay");
const closeBtn = document.querySelector(".close-btn");

modalBtn.addEventListener("click", function () {
  modal.classList.add("open-modal");
});
closeBtn.addEventListener("click", function () {
  modal.classList.remove("open-modal");
});
Select the modal, modal button, and close button using document.querySelector

Add a click event listener to the modal button to add a class (e.g., .open-modal) to the modal overlay, changing its visibility to visible. 

Similarly, attach a click event listener to the close button to remove the .open-modal class and hide the modal.

Testing - Open index.html in Browser

Let's open the index.html file in the browser, and you will be able to see the following screen:

Comments