Sample:
Code:
<style>
[role="dialog"] {
align-items: center;
background: rgb( 0 0 0 / 0.2);
inset: 0;
justify-content: center;
margin: auto;
position: fixed;
}
[role="dialog"]:not([hidden]) {
display: flex;
}
[role="dialog"] > div {
background: rgb(255 255 255);
box-sizing: border-box;
max-width: 40rem;
padding: 2rem;
width: 90vw;
}
:focus-visible {
outline: 4px solid #123456;
outline-offset: 4px;
}
[role="dialog"]:focus-visible {
outline-offset: -8px;
}
</style>
<button class="open">Login</button>
<div role="dialog" aria-modal="true" hidden aria-labelledby="heading">
<div>
<button class="close">Close</button>
<h1 id="heading" tabindex="-1">Login</h1>
</div>
</div>
<script>
const dialogOpen = document.querySelector('.open')
const dialogClose = document.querySelector('.close')
const dialog = document.querySelector('[role="dialog"]')
const heading = dialog.querySelectorAll('[tabindex="-1"]')[0]
let trigger
dialogOpen.addEventListener('click', open)
dialogClose.addEventListener('click', close)
function open() {
trigger = document.activeElement
dialogToggle()
}
function close () {
dialogToggle()
}
function dialogToggle() {
const isOpen = !dialog.hasAttribute('hidden')
if (!isOpen) {
dialog.removeAttribute('hidden')
heading.focus()
} else {
dialog.setAttribute('hidden', 'hidden')
trigger.focus()
}
}
</script>