Don’t hesitate to contact us if you have any feedback.

Implementing Custom Popups with HTML, CSS, and JavaScript

Creating interactive popups can greatly enhance user engagement on websites. This implementation showcases a simple yet effective way to create custom popups using native HTML <dialog> elements, accompanied by CSS for styling and JavaScript for functionality.

HTML Structure for Popups

The HTML structure includes two main sections: one with buttons to trigger the popups and another with the popup <dialog> elements themselves, each containing a subscription form.

<main>
    <!-- Trigger buttons for the popups -->
    <section class="cta-wrapper">
        <button class="modal-opener" data-modal="#modal-newsletter">
            Open popup
        </button>

        <button class="modal-opener" data-modal="#modal-newsletter-2">
            Open popup 2
        </button>
    </section>

    <!-- Dialog elements (popups) -->
    <dialog class="modal" id="modal-newsletter">
        <button class="button-close-modal">X</button>
        <h2>Subscribe to my Newsletter</h2>
        <p>Get access to exclusive content that only share with my email list</p>
        <label for="email">Enter your email:</label>
        <input type="email" id="email" name="email" />
    </dialog>

    <dialog class="modal" id="modal-newsletter-2">
        <button class="button-close-modal">X</button>
        <h2>Another modal</h2>
        <p>Get access to exclusive content that only share with my email list</p>
        <label for="email-2">Enter your email:</label>
        <input type="email" id="email-2" name="email" />
    </dialog>
</main>

Styling with CSS

The CSS ensures that the popups are visually distinct and properly layered over other content. A no-scroll class is also defined to prevent scrolling when a popup is active.

html {
    height: 100%;
}

body {
    margin: 0;
    min-height: 100%;
    display: grid;
    grid-auto-flow: row;
    grid-template-rows: auto 1fr auto;
}

body.no-scroll {
    margin-right: var(--scrollbarsize);
    overflow: hidden;
}

.modal {
    padding: 2rem;
    border: 1px solid #eee;
    width: max-content;
    max-width: 100%;
    background-color: #fff;
    z-index: 10;
}

.modal::backdrop {
    background-color: hsl(250, 100%, 50%, 0.25);
}

.button-close-modal {
    display: block;
    font-size: 2rem;
    font-weight: bold;
    margin-left: auto;
}

Interactive functionality with JavaScript

The JavaScript code listens for the DOMContentLoaded event to ensure the DOM is fully loaded before attaching event listeners to the buttons and dialog elements for opening and closing the popups.

window.addEventListener("DOMContentLoaded", (event) => {
    // Loop through the buttons and attach a listener to open the associated modals
    const openModalButtons = document.querySelectorAll(".modal-opener");
    if (openModalButtons.length) {
        openModalButtons.forEach((openButton) => {
            const associatedId = openButton.dataset.modal;
            if (associatedId) {
                const dialog = document.querySelector(associatedId);
                if (dialog) {
                    // Listener for opening the modal
                    openButton.addEventListener("click", (e) => {
                        // Set the size of the scrollbar as a CSS variable
                        document.documentElement.style.setProperty(
                            "--scrollbarsize",
                            `${window.innerWidth - document.documentElement.clientWidth}px`
                        );
                        // Open the associated modal
                        dialog.showModal();
                        // Prevent the user from scrolling
                        document.body.classList.add("no-scroll");
                    });

                    // Listener for closing the modal
                    dialog.addEventListener("click", (e) => {
                        const dialogDimensions = dialog.getBoundingClientRect();
                        if (
                            e.clientX < dialogDimensions.left ||
                            e.clientX > dialogDimensions.right ||
                            e.clientY < dialogDimensions.top ||
                            e.clientY > dialogDimensions.bottom ||
                            e.target.matches(".button-close-modal")
                        ) {
                            // Close the open modal
                            dialog.close();
                            // Re-enable scrolling
                            document.body.classList.remove("no-scroll");
                        }
                    });
                } else {
                    console.log(
                        'No associated modal found; maybe the "data-modal" attribute is empty or incorrect.'
                    );
                }
            }
        });
    }
});

Complete code integration

See the Pen Custom Popups with HTML, CSS, and JavaScript by LaTableRouge (@LaTableRouge) on CodePen.

Additional resources

For detailed documentation and best practices related to the <dialog> element and its usage, the following resources can be helpful:

This simple yet robust implementation allows developers to integrate custom popups into their web projects, enhancing the user interface and interaction without the need for third-party libraries.


Comments

Leave a Reply

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