Modal Component #

Description #

The Modal component provides an overlay window that can contain content, messages, or actions. It supports both static and draggable types, can be bounded within the viewport, and optionally remembers its last position when closed and reopened.

Examples and Classes #

Static Modal Example

            

HTML

<button class="modal-toggle btn btn-success" data-modal-id="example1">open</button> <dialog id="example1" class="modal-container"> <div class="modal-content"> <div class="modal-header"> <i class="modal-close secondary-color fa-solid fa-close w-fit-content"></i> </div> <div class="modal-body"> <p class="txt-high-title secondary-color">Modal Title</p> <p class="txt-normal secondary-color ">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam. </p> <div class="d-flex align-items-center gap-2"> <button class="btn btn-outline-danger modal-close">close</button> <button class="btn btn-secondary">link</button> </div> </div> </div> </dialog>

Draggable Modal Example

            

HTML

<button class="modal-toggle btn btn-success" data-modal-id="example2">open</button> <dialog id="example2" class="modal-container modal-draggable"> <div class="modal-content"> <div class="modal-header"> <i class="modal-close secondary-color fa-solid fa-close w-fit-content"></i> </div> <div class="modal-body"> <p class="txt-high-title secondary-color">Modal Title</p> <p class="txt-normal secondary-color">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam. </p> <div class="d-flex align-items-center gap-2"> <button class="btn btn-outline-danger modal-close">close</button> <button class="btn btn-secondary">link</button> </div> </div> </div> </dialog>

Draggable Modal With Bound Example

            

HTML

<button class="modal-toggle btn btn-success" data-modal-id="example3">open</button> <dialog id="example3" class="modal-container modal-draggable modal-bounds"> <div class="modal-content"> <div class="modal-header"> <i class="modal-close secondary-color fa-solid fa-close w-fit-content"></i> </div> <div class="modal-body"> <p class="txt-high-title secondary-color">Modal Title</p> <p class="txt-normal secondary-color ">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam. </p> <div class="d-flex align-items-center gap-2"> <button class="btn btn-outline-danger modal-close">close</button> <button class="btn btn-secondary">link</button> </div> </div> </div> </dialog>

Draggable Modal With Remember Position Example

            

HTML

<button class="modal-toggle btn btn-success" data-modal-id="example4">open</button> <dialog id="example4" class="modal-container modal-draggable modal-remember-position"> <div class="modal-content"> <div class="modal-header"> <i class="modal-close secondary-color fa-solid fa-close w-fit-content"></i> </div> <div class="modal-body"> <p class="txt-high-title secondary-color">Modal Title</p> <p class="txt-normal secondary-color ">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam. </p> <div class="d-flex align-items-center gap-2"> <button class="btn btn-outline-danger modal-close">close</button> <button class="btn btn-secondary">link</button> </div> </div> </div> </dialog>

Draggable Modal With Bound And Remember Position Example

            

HTML

<button class="modal-toggle btn btn-success" data-modal-id="example5">open</button> <dialog id="example5" class="modal-container modal-draggable modal-bounds modal-remember-position"> <div class="modal-content"> <div class="modal-header"> <i class="modal-close secondary-color fa-solid fa-close w-fit-content"></i> </div> <div class="modal-body"> <p class="txt-high-title secondary-color">Modal Title</p> <p class="txt-normal secondary-color ">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pulvinar risus non risus hendrerit venenatis. Pellentesque sit amet hendrerit risus, sed porttitor quam.Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam. </p> <div class="d-flex align-items-center gap-2"> <button class="btn btn-outline-danger modal-close">close</button> <button class="btn btn-secondary">link</button> </div> </div> </div> </dialog>
Class Description Example
.modal-container Defines the main modal wrapper using the native <dialog> element. Acts as the base container for all modal content and supports styling, positioning, and animation. <dialog class="modal-container">...</dialog>
.modal-content Wraps all modal content including header, body, and footer with consistent padding, background, and shadow. <div class="modal-content">...</div>
.modal-header Defines the header area of the modal, typically containing the title and close icon. <div class="modal-header"><h3>Title</h3><i class="modal-close fa-solid fa-close"></i></div>
.modal-body Represents the main content area of the modal where text, forms, or other elements appear. <div class="modal-body">...</div>
.modal-footer Defines the footer area, typically used for action buttons such as “Cancel” or “Save”. <div class="modal-footer"><button>Save</button></div>
.modal-close Used for elements that close the modal. Automatically closes its parent modal when clicked. <i class="modal-close fa-solid fa-close"></i>
.modal-draggable Makes the modal draggable inside the viewport. Works with .modal-bounds. <dialog class="modal-container modal-draggable"></dialog>
.modal-bounds Limits the draggable area to the visible screen boundaries. <dialog class="modal-container modal-bounds"></dialog>
.modal-remember-position Stores the last dragged position and restores it when reopened. <dialog class="modal-container modal-remember-position"></dialog>
.modal-toggle Used on buttons to open or close a modal by referencing its ID via data-target. <button class="modal-toggle" data-target="#modalStatic">Open Modal</button>

File Locations #

Type Path
SCSS miz/themes/mizoon/components/modal/_index.scss
HTML Example miz/themes/mizoon/components/modal/index.html
JavaScript miz/themes/mizoon/components/modal/script.js

SCSS Variables #

        

SCSS

$modal-container-custom-classes: ".bg-transparent-color, .justify-content-center, .align-items-center"; $modal-content-custom-classes: ".d-flex, .flex-column, .bg-section-color, .radius-all-small, .overflow-hidden, .w-30"; $modal-content-header-custom-classes: ".d-flex, .flex-column, .gap-2, .p-2, .bg-on-secondary-color"; $modal-content-body-custom-classes: ".d-flex, .flex-column, .gap-2, .p-2"; $modal-content-footer-custom-classes: ".d-flex, .flex-column, .gap-2, .p-2"; $modal-close-custom-classes: ".cursor-pointer"; $modal-content-animation: 0.3s ease-out forwards; $modal-dragging-transition: 0.07s ease-out;

JavaScript #

Below is an example of initializing and managing modal behavior using JavaScript.

            

JavaScript

class Modal { constructor() { this.initialPositions = new Map() this.init() } init() { this.initToggles() this.initClose() this.initDraggable() } initToggles() { document.querySelectorAll(".modal-toggle").forEach(btn => { const id = btn.dataset.modalId btn.addEventListener("click", () => { const modal = document.getElementById(id) if (!modal) return const modalContent = modal.querySelector(".modal-content") modal.style.display = "flex" modal.classList.remove("hide") modal.classList.add("show") modalContent.addEventListener("animationend", () => { if (modal.classList.contains("modal-remember-position") && modal.dataset.position) { try { const { top, left } = JSON.parse(modal.dataset.position) modalContent.style.position = "absolute" modalContent.style.top = `${top}px` modalContent.style.left = `${left}px` return } catch (e) { } } if (!this.initialPositions.has(modal)) { const rect = modalContent.getBoundingClientRect() const scrollTop = window.scrollY || window.pageYOffset const scrollLeft = window.scrollX || window.pageXOffset this.initialPositions.set(modal, { top: rect.top + scrollTop, left: rect.left + scrollLeft }) } const initial = this.initialPositions.get(modal) if (initial) { modalContent.style.position = "absolute" modalContent.style.top = `${initial.top}px` modalContent.style.left = `${initial.left}px` } }, { once: true }) }) }) } initClose() { document.querySelectorAll(".modal-close").forEach(btn => { btn.addEventListener("click", () => { const modal = btn.closest(".modal-container, .modal-draggable") if (!modal) return const modalContent = modal.querySelector(".modal-content") modal.classList.remove("show") modal.classList.add("hide") modal.addEventListener("animationend", () => { if (!modal.classList.contains("hide")) return if (!modal.classList.contains("modal-remember-position") && modalContent) { const initial = this.initialPositions.get(modal) if (initial) { modalContent.style.top = `${initial.top}px` modalContent.style.left = `${initial.left}px` } } modal.style.display = "none" modal.classList.remove("hide") }, { once: true }) }) }) } initDraggable() { document.querySelectorAll(".modal-draggable .modal-content .modal-header").forEach(header => { let isDragging = false let offsetX = 0 let offsetY = 0 const modalContent = header.closest(".modal-content") const modalContainer = header.closest(".modal-draggable") header.addEventListener("mousedown", e => { if (e.target.classList.contains("modal-close") || e.target.tagName === "BUTTON") return isDragging = true modalContent.classList.add("dragging") const rect = modalContent.getBoundingClientRect() modalContent.style.left = `${rect.left + (window.scrollX || window.pageXOffset)}px` modalContent.style.top = `${rect.top + (window.scrollY || window.pageYOffset)}px` modalContent.style.position = "absolute" modalContent.style.margin = "0" modalContent.style.zIndex = 9999 offsetX = e.clientX - rect.left offsetY = e.clientY - rect.top }) document.addEventListener("mousemove", e => { if (!isDragging) return let newLeft = e.clientX - offsetX let newTop = e.clientY - offsetY if (modalContainer.classList.contains("modal-bounds")) { const modalRect = modalContent.getBoundingClientRect() const winWidth = window.innerWidth const winHeight = window.innerHeight if (newLeft < 0) newLeft = 0 if (newTop < 0) newTop = 0 if (newLeft + modalRect.width > winWidth) newLeft = winWidth - modalRect.width if (newTop + modalRect.height > winHeight) newTop = winHeight - modalRect.height } modalContent.style.left = `${newLeft}px` modalContent.style.top = `${newTop}px` }) document.addEventListener("mouseup", () => { if (!isDragging) return isDragging = false modalContent.classList.remove("dragging") if (modalContainer.classList.contains("modal-remember-position")) { modalContainer.dataset.position = JSON.stringify({ top: parseFloat(modalContent.style.top), left: parseFloat(modalContent.style.left) }) } }) }) } } new Modal()
To use this component, you need to:

Include the MIZCHIN JavaScript file in your page.