Published: January 04 2023

Vanilla JS + CSS - Modal Popup (Dialog) Tutorial with Example

Example built with Vanilla JS and CSS

Other versions available:

This is a quick post to show how easy it is to implement modal popups in pure HTML, CSS and JavaScript.

JS + CSS Example App

The example app contains a single page with some text and a couple of buttons to open two modal popups:

  • Modal #1 - a simple custom modal popup.
  • Modal #2 - a tall popup to demonstrate that the modal is scrollable while keeping the page below locked in position.

Here it is in action: (See on StackBlitz at

The HTML, CSS and JavaScript Code

The example app consists of just three files for the HTML, Vanilla JS and CSS code:


Modal HTML

Path: /index.html

The index.html file contains three main div elements, one for the page heading and buttons to open the modals (modal-1 and modal-2), and two divs for the modals themselves.

It includes styles.css and script.js in the head to handle modal styling and behaviour.

Unique id required

Each modal must have a unique id attribute (e.g. <div id="modal-1">), it is used to identify which modal you want to open when calling the open modal function (e.g. openModal('modal-1')).

<!DOCTYPE html>
    <title>Vanilla JS + CSS - Modal Popup Example</title>
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" href="styles.css" />
    <script src="script.js"></script>

    <!-- main app container -->
            <h1>Vanilla JS + CSS - Modal Popup Example</h1>
            <p>Click the buttons below to open the example modals</p>
            <button onclick="openModal('modal-1')">Open Modal 1</button>
            <button onclick="openModal('modal-2')">Open Modal 2</button>

        <div id="modal-1" class="jw-modal">
            <div class="jw-modal-body">
                <h1>A custom modal popup</h1>
                <button onclick="closeModal()">Close</button>

        <div id="modal-2" class="jw-modal">
            <div class="jw-modal-body">
                <h1>A tall modal popup</h1>
                <p style="padding-bottom: 1500px;">Close with the button below or by clicking the background.</p>
                <button onclick="closeModal()">Close</button>


Modal JavaScript

Path: /script.js

JavaScript is used to implement modal behaviour, i.e. opening and closing modal popups.

Modal functions

openModal() - makes the modal appear by adding the CSS class open to the modal element. Adds the jw-modal-open CSS class to the <body> tag to lock scrolling on the underlying body.

closeModal() - makes the modal disappear by removing the open class from the modal element. Removes the jw-modal-open CSS class from the <body> tag to unlock scrolling on the body.

Close on background click

On window load a 'click' event listener is added to the document to close any modal on background click.

// open modal by id
function openModal(id) {

// close currently open modal
function closeModal() {

window.addEventListener('load', function() {
    // close modals on background click
    document.addEventListener('click', event => {
        if ('jw-modal')) {

Modal CSS Styles

Path: /styles.css

This stylesheet is the main file in the modal tutorial, the below CSS styles are what turn a couple of divs in the HTML into modal popups in your browser. The javascript code just controls opening and closing.

General styles

The top of the file contains a few styles to pretty up the example a bit since it doesn't use Bootstrap or anything other CSS.

Modal styles

.jw-modal - the root element of each modal is set to hidden (closed) by default. The outer container div is fixed across the whole screen above all other elements with a semi-transparent black background and scrolling enabled in case the content is longer than the screen. - the root modal element is visible when it includes the open class.

.jw-modal-body - the inner container div just has a white background and some padding.

body.jw-modal-open - this class is added to the HTML <body> tag when a modal is open. Scrolling is disabled on the underlying body content when a modal is open above.

Prefixed with jw-

I prefixed the modal classes with jw- to prevent name clashes with any 3rd party CSS libraries you might be using (e.g. Bootstrap).

body {
    font-family: Arial, Helvetica, sans-serif;
    padding: 20px;

h1 {
    font-weight: normal;
    margin-top: 0;

button {
    padding: 7px 10px;
    margin-right: 5px;

.jw-modal {
    /* modals are hidden by default */
    display: none;

    /* modal container fixed across whole screen */
    position: fixed;
    inset: 0;

    /* z-index must be higher than everything else on the page */
    z-index: 10000;
    /* semi-transparent black background exposed by padding */
    background-color: rgba(0, 0, 0, .75);
    padding: 40px;

    /* enables scrolling for tall modals */
    overflow: auto;
} {
    display: block;

.jw-modal-body {
    padding: 20px;
    background: #fff;

body.jw-modal-open {
    /* body overflow is hidden to hide main scrollbar when modal window is open */
    overflow: hidden;


Need Some Vanilla JS Help?

Search fiverr for freelance Vanilla JS developers.

Follow me for updates

On Twitter or RSS.

When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Supported by