Modals – Popup
Κώδικας έτοιμος για styling
No Background scrolling, εύκολο html markup κτλ

Δημοσιεύθηκε 20/06/2021

Στο παρόν άρθρο θα βρεις έτοιμο lightweight κώδικα για να δημιουργείς Modals popup στις ιστοσελίδες, με πολύ εύκολο και απλό html markup.

Ο κώδικας έχει δημιουργηθεί για προσωπικές ανάγκες αλλά θεωρώ πως θα είναι χρήσιμος και για άλλους.

Το μόνο που χρειάζεται είναι να γράψουμε απευθείας το html markup για τα modals, και να δημιουργήσουμε το σχετικό styling όπως το επιθυμούμε χωρίς να χρειάζεται να κάνουμε override styling καθώς έχω περάσει μόνο τον απολύτως απαραίτητο κώδικα. Έγραψα vanilla JavaScript ο οποίος είναι έτοιμος για χρήση χωρίς να χρειαστεί κάποια μετατροπή.

Modals: ιδιαίτερα χαρακτηριστικά

  • Δυνατότητα χρήσης πολλαπλών modals στην ίδια σελίδα – (όχι ταυτόχρονο άνοιγμα πολλαπλών modals)
  • Δυνατότητα εύκολης ενσωμάτωσης κουμπιού κλεισίματος του modal
  • Κλείσιμο modal όταν γίνεται κλικ εκτός του modal, δηλαδή στο σχετικό overlay που δημιουργείται αυτόματα (μέσω του javascript κώδικα) πίσω από το modal
  • Απενεργοποίηση του background scrolling όταν το modal είναι ανοιχτό
  • Τα modals με μεγάλο περιεχόμενο που ξεπερνάνε το viewport εμφανίζουν το κλασσικό scrollbar για εμφάνιση του περιεχομένου – έτσι μπορούμε άνετα να βάλουμε όσο περιεχόμενο θέλουμε χωρίς περιορισμό

Modals κώδικας με παράδειγμα για το html markup

Javascript

Το ενσωματώνουμε ως έχει στο project μας

// Create DOM overlay
let nb_modal_overlay = document.createElement("div");
nb_modal_overlay.id = "nb_modal_overlay";
document.body.appendChild(nb_modal_overlay);

// Get Buttons
const nb_modals_buttons = document.querySelectorAll("[data-nb_modal_target]");
const nb_modals_close_buttons = document.querySelectorAll("[data-nb_modal_close_button]");

if (nb_modal_overlay) {
    if (nb_modals_buttons) {
        nb_modals_buttons.forEach((button) => {
            button.addEventListener("click", () => {
                let nb_modal = document.querySelector(button.dataset.nb_modal_target);
                nb_open_modal(nb_modal);
            });
        });
    }

    nb_modal_overlay.addEventListener("click", () => {
        let nb_modal = document.querySelector(".active[data-nb_modal]");
        nb_close_modal(nb_modal);
    });

    if (nb_modals_close_buttons) {
        nb_modals_close_buttons.forEach((close_button) => {
            close_button.addEventListener("click", () => {
                let nb_modal = close_button.closest("[data-nb_modal]");
                nb_close_modal(nb_modal);
            });
        });
    }
}

// ---------
// FUNCTIONS
// ---------
function nb_open_modal(modal) {
    if (modal == null) return;
    modal.classList.add("active");
    nb_modal_overlay.classList.add("active");
    nb_disable_body_scrolling();
}

function nb_close_modal(modal) {
    if (modal == null) return;
    modal.classList.remove("active");
    nb_modal_overlay.classList.remove("active");
    nb_enable_body_scrolling();
}

// Disable BODY - background scrolling
function nb_disable_body_scrolling() {
    document.body.style.overflow = "hidden";
}

// Enable BODY - background scrolling
function nb_enable_body_scrolling() {
    document.body.style.overflow = "";
}

CSS

#nb_modal_overlay {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    cursor: pointer;
    z-index: 900;

    /* Custom */
    background-color: rgba(0, 0, 0, 0.5);
    transition: opacity 0.4s ease;
}
#nb_modal_overlay.active {
    opacity: 1;
    visibility: visible;
    pointer-events: all;
}

[data-nb_modal] {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: fit-content;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 950;

    /* Custom */
    transition: opacity 0.4s ease;
}
.active[data-nb_modal] {
    opacity: 1;
    visibility: visible;
    pointer-events: all;
}

[data-nb_modal_content] {
    position: relative;
    overflow-y: auto;
    margin: 15px;

    /* Custom */
    max-height: 97vh;
    background-color: #fff;
    padding: 40px;
    max-width: 800px;
}

[data-nb_modal_close_button] {
    background-color: transparent;
    border: none;
    cursor: pointer;

    /* Custom */
    position: absolute;
    right: 15px;
    top: 15px;
}

HTML

Είναι απαραίτητο να διατηρήσουμε όλα τα data attributes ως έχουν

  • data-nb_modal_target: Σε ένα button, ή ακόμα και σε a tag δηλώνουμε το id του modal
  • To data-nb_modal_target element δεν είναι απαραίτητο να ακολουθείται από το data-nb_modal. Το nb_modal μπορεί να βρίσκεται οπουδήποτε μέσα στην σελίδα.
  • <button data-nb_modal_close_button>: Είναι προαιρετικό αν θέλουμε να εμφανιστεί κάποιο button κλεισίματος στο modal
<button data-nb_modal_target="#thisModal">Click me to open modal</button>


<div id="thisModal" data-nb_modal>
    <div data-nb_modal_content>
        <button data-nb_modal_close_button>
            <svg width="21" height="21" viewBox="0 0 21 21"><path d="M28.5,9.615,26.385,7.5,18,15.885,9.615,7.5,7.5,9.615,15.885,18,7.5,26.385,9.615,28.5,18,20.115,26.385,28.5,28.5,26.385,20.115,18Z" transform="translate(-7.5 -7.5)" /></svg>
        </button>
        <p>Το περιεχόμενο του modal. Μπορείς να χρησιμοποιήσεις εικόνες, div tag ... οτιδήποτε</p>
    </div>
</div>

Ο παραπάνω κώδικας υπάρχει και στον Github λογαριασμό μου.