<body>
<div class="main-content">
main content
<trigger-modal name="my-modal">
<label>
open modal
<input type="checkbox" role="button" form="modal-form-my-modal">
</label>
</trigger-modal>
</div>
<dialog-modal name="my-modal" main-content-class="main-content">
<div id="modal-container-my-modal">
<button class="modal-overlay" tabindex="-1" form="modal-form-my-modal" type="reset"></button>
<div class="modal-body" role="dialog">
<button tabindex="-1" form="modal-form-my-modal" type="reset">x</button>
Dialog 1
<close-modal name="my-modal">
<button type="reset" form="modal-form-my-modal">
Close Modal
</button>
</close-modal>
</div>
<form id="modal-form-my-modal"></form>
</div>
</dialog-modal>
</body>
trigger-modal label > input {
opacity: 0;
position: absolute;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
clip-path: inset(50%);
}
trigger-modal label {
border: 1px solid black;
border-radius: 3px;
font-style: san-serif;
padding: 2px 5px;
}
trigger-modal label:focus-within {
outline: 1px dashed red;
}
body {
position: relative;
}
.main-content {
position: absolute;
}
dialog-modal > div {
display: none;
height: 100vh;
width: 100vw;
position: absolute;
}
dialog-modal > div > button.modal-overlay {
height: 110vh;
width: 110vw;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
opacity: 0.6;
background-color: black;
}
dialog-modal > div > .modal-body {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 1rem;
background: white;
}
/* Set main to visibility hidden if modal open */
/* :not([inert]) so when PE inert added visibility is not used */
.main-content:not([inert]):has(input[form="modal-form-my-modal"]:checked) {
visibility: hidden;
}
/* Set modal to visible if modal open */
body:has(input[form="modal-form-my-modal"]:checked) #modal-container-my-modal {
display: block;
}
/* ignore basic styles below */
html {
margin: auto;
line-height: 1.75;
font-size: 1.25em;
}
button {
font-style: san-serif;
padding: 2px 5px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 3em 0 1em;
}
p,
ul,
ol {
margin-bottom: 2em;
color: #1d1d1d;
font-family: sans-serif;
}
// To simulate disabling JS comment out the
// customElements.define at the bottom of page
class DialogModal extends HTMLElement {
constructor() {
super();
this.form = this.querySelector("form");
this.inertMain = this.inertMain.bind(this);
this.unInertMain = this.unInertMain.bind(this);
this.escClose = this.escClose.bind(this);
this.enterOpen = this.enterOpen.bind(this);
this.form.addEventListener("reset", this.unInertMain);
window.addEventListener("keyup", this.escClose);
}
connectedCallback() {
this.mainContentClass = this.getAttribute("main-content-class");
this.mainContent = document.querySelector("." + this.mainContentClass);
this.name = this.getAttribute("name");
this.allTriggers = document.querySelectorAll(
"input[type=checkbox][form=modal-form-" + this.name + "]"
);
this.allTriggers.forEach((trigger) => {
trigger.addEventListener("change", this.inertMain);
trigger.addEventListener("keydown", this.enterOpen);
});
}
disconnectedCallback() {
this.allTriggers.forEach((trigger) => {
trigger.removeEventListener("change", this.inertMain);
trigger.removeEventListener("keydown", this.enterOpen);
});
this.form.removeEventListener("reset", this.unInertMain);
window.removeEventListener("keyup", this.escClose);
}
inertMain() {
this.mainContent.setAttribute("inert", "");
}
unInertMain() {
this.mainContent.removeAttribute("inert");
}
enterOpen(e) {
if (e.code === "Enter") {
e.target.checked = true;
this.inertMain();
}
}
escClose(e) {
if (e.code === "Escape") {
this.form.reset();
}
}
}
customElements.define("dialog-modal", DialogModal);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.