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;


Subscribe or Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter, Facebook or GitHub to be notified when I post new content.

Other than coding...

I'm currently attempting to travel around Australia by motorcycle with my wife Tina on a pair of Royal Enfield Himalayans. You can follow our adventures on YouTube, Instagram and Facebook.

Need Some Vanilla JS Help?

Search fiverr to find help quickly from experienced Vanilla JS developers.

Supported by