<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/assets/reset.css" rel="stylesheet">
<link href="setup.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
<script defer src="script.js"></script>
</head>
<body>
<button id="modal">Click here!</button>
<dialog id="dialog">
<p>This is a modal with an overlay!</p>
<button>Close it!</button>
</dialog>
</body>
</html>
index.html
// Similar to before, setting up variables.
let modalButton = document.querySelector('#modal') // The thing we’re clicking.
let modalDialog = document.querySelector('#dialog') // Now one for our `dialog`.
let closeButton = modalDialog.querySelector('button') // Only looking within `modalDialog`.
modalButton.addEventListener('click', () => { // “Listen” for clicks.
modalDialog.showModal() // This opens it up.
})
closeButton.addEventListener('click', () => {
modalDialog.close() // And this closes it!
})
// Listen to *all* clicks, now including the `event` parameter…
document.addEventListener('click', (event) => {
// Only clicks on the page itself behind the `dialog`.
if (event.target == document.documentElement) {
modalDialog.close() // Close it too then.
}
})
/* Stops the page from scrolling when there is an open one: */
body:has(dialog[open]) { overflow: hidden; }
dialog {
/* Style the `dialog` itself, which is `display: none;` to start. */
background-color: white;
border-radius: var(--base);
filter: drop-shadow(0 0.5rem 1rem rgb(0 0 0 / 50%)); /* Some depth. */
gap: calc(2 * var(--base));
justify-items: center; /* Center the children. */
padding: var(--base);
/* Defaults to `position: absolute;`, this centers it: */
inset-block-start: 50%;
inset-inline-start: 50%;
position: fixed; /* In the viewport. */
translate: -50% -50%;
/* When JS adds the `open` attribute… */
&[open] { display: grid } /* `block` is default, but we can override. */
button { background-color: tomato; } /* Always have a clear “close” `button`! */
&::backdrop {
background-color: rgb(0 0 0 / 66%); /* A dark overlay. */
pointer-events: none; /* Let clicks pass through to our `document` listener. */
}
}