Dialogs
Native HTML <dialog>
elements with optional transition animation styles and light-dismiss.
Examples
The dialogs use a script and method from Fun with the dialog element by Mark Otto that uses data-attributes with unique IDs to provide the opening and closing functionality, but if required a form method="dialog"
button can also be combined with the technique for closing dialogs containing form content.
Example HTML
<button data-dialog="#dialog">Basic</button>
<dialog id="dialog">
<h2>Basic</h2>
<p>Uses script for the opening and closing buttons.</p>
<button class="close-dialog">Close</button>
</dialog>
<button data-dialog="#dialog-form">Form method</button>
<dialog id="dialog-form">
<h2>Form method</h2>
<p>Uses script for opening and form method button for closing.</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
Script
let toggler = document.querySelectorAll("[data-dialog]"),
closers = document.querySelectorAll(".close-dialog");
toggler &&
(toggler.forEach(function (e) {
let l = e.getAttribute("data-dialog"),
t = document.querySelectorAll(l);
e.addEventListener("click", (e) => {
t.forEach(function (e) {
e.showModal();
});
});
}),
closers.forEach(function (e) {
e.addEventListener("click", (l) => {
e.closest("dialog").close();
});
}));
Light-dismiss
Placed as the last child within the dialog the <div class="close-dialog"></div>
is styled as a background element that uses the script closing functionality to enable clicking outside the dialog to close it.
Example HTML
<button data-dialog="#dialog-light-dismiss">Basic light-dismiss</button>
<dialog id="dialog-light-dismiss">
<h2>Light-dismiss</h2>
<p>Uses script for opening, closing and light-dismiss.</p>
<button class="close-dialog">Close</button>
<div class="close-dialog"></div>
</dialog>
<button data-dialog="#dialog-form-light-dismiss">Form method light-dismiss</button>
<dialog id="dialog-form-light-dismiss">
<h2>Form method</h2>
<p>Uses script for opening and form method button for closing.</p>
<form method="dialog">
<button>Close</button>
</form>
<div class="close-dialog"></div>
</dialog>
Transition
The optional transition animation style can be customized inline using the CSS variable --dialog-transition
.
Examples HTML
The dialog animation is enabled for this website so the 'No transition' example uses the variable to remove the default .25s transition included to demonstrate default non-animated dialogs.
<button data-dialog="#default-transition">No transition</button>
<dialog id="default-transition" style="--dialog-transition: 0s;">
<h2>Heading basic</h2>
<p>The quick brown fox jumps over the lazy dog.</p>
<button class="close-dialog">Close</button>
<div class="close-dialog"></div>
</dialog>
<button data-dialog="#transition-enabled">Enabled (default .25s)</button>
<dialog id="transition-enabled">
<h2>Heading basic</h2>
<p>The quick brown fox jumps over the lazy dog.</p>
<button class="close-dialog">Close</button>
<div class="close-dialog"></div>
</dialog>
<button data-dialog="#transition-custom">Enabled (custom 1.5s)</button>
<dialog id="transition-custom" style="--dialog-transition: 1.5s;">
<h2>Heading basic</h2>
<p>The quick brown fox jumps over the lazy dog.</p>
<button class="close-dialog">Close</button>
<div class="close-dialog"></div>
</dialog>
Using the module
Add the sassmods.scss
to your custom styles as below then include the Sass mixin(s) anywhere below.
@use "sassmods/scss/sassmods" as *;
@include dialogs-css;
@include dialogs-animation-css;
See customizing for information about using the Sass and CSS variables in the source code (see below) to customize the styles, and Sass variables (on the using SassMods page) for other ways to use the variables to create custom styles.
Source
_dialogs.scss
// ----------------------------------------------------------
// Dialogs
// ----------------------------------------------------------
$dialog-text-color: var(--dialog-text) !default;
$dialog-margin-top: var(--dialog-mt, 1rem) !default;
$dialog-padding-block: var(--dialog-py, 0.75rem) !default;
$dialog-padding-inline: var(--dialog-px, 1rem) !default;
$dialog-border-color: var(--dialog-bd-color, color-mix(in srgb, CanvasText 12%, Canvas)) !default;
$dialog-radius: var(--dialog-radius, 0.125em) !default;
$dialog-background-color: var(--dialog-bg, Canvas) !default;
$dialog-transition: var(--dialog-transition, 0.25s) !default;
$dialog-backdrop: color-mix(in srgb, black 50%, transparent) !default;
@mixin dialogs-css {
:where(dialog) {
color: $dialog-text-color;
block-size: fit-content;
max-block-size: calc(100vh - 2rem);
inline-size: calc((100% - 6px) - 2em);
max-inline-size: var(--dialog-width, fit-content);
margin-block-start: $dialog-margin-top;
padding-block: $dialog-padding-block;
padding-inline: $dialog-padding-inline;
border: 1px solid $dialog-border-color;
border-radius: $dialog-radius;
background-color: $dialog-background-color;
overflow: auto;
overscroll-behavior: contain;
}
dialog div[class="close-dialog"] {
position: fixed;
inset: 0;
z-index: -1;
display: block;
content: "";
}
dialog[open]::backdrop {
background-color: $dialog-backdrop;
}
} // end dialogs-css
@mixin dialogs-animation-css {
@media screen and (prefers-reduced-motion: no-preference) {
dialog[open] {
transition: $dialog-transition;
opacity: 1;
}
}
@starting-style {
dialog[open] {
opacity: 0;
}
}
}