<dialog> improvements (closedby, :modal, requestClose)
`<dialog>` + `:modal` Baseline 2022. Atributo `closedby`: Chrome 134, Firefox 137; Safari pendiente (elemento de Interop 2026), así que no es Baseline a fecha 2026-09.
Chrome 134
Edge 134
Safari no
Firefox 137
Los diálogos modales nativos traen el atrapado de foco correcto, la inercia de la página y la gestión de Escape. `closedby="any"` añade cierre ligero (clic fuera cierra), `closedby="none"` bloquea Escape, sin listeners de JS.
CSS
.fx-013 {
border: 0;
border-radius: 14px;
padding: 24px;
max-width: 360px;
box-shadow: 0 20px 60px #0004;
font-family: system-ui
}
.fx-013::backdrop {
background: #0006;
backdrop-filter: blur(3px)
}
.fx-013:modal {
margin: auto
}
@starting-style {
.fx-013:open {
opacity: 0;
translate: 0 12px
}
}
.fx-013:open {
transition: opacity .2s,translate .2s
}
.fx-013 :is(a,button,input,select,textarea):focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
HTML
<button class="fx-013-btn" onclick="document.getElementById('fx-013').showModal()">Open dialog</button>
<dialog id="fx-013" class="fx-013" closedby="any">
<h3>Confirm</h3><p>Click outside or press Escape to dismiss.</p>
<form method="dialog"><button>Done</button></form>
</dialog>Fallback: Sin `closedby`, solo Escape cierra; añade un manejador de clic en el diálogo que compruebe `event.target === dialog` donde haga falta cierre ligero.
Prompt
Usa el elemento nativo `<dialog>` con `showModal()` para los modales; estiliza la capa atenuada con `::backdrop`, usa formularios `method="dialog"` para cerrar y añade `closedby="any"` para el cierre ligero (Safari no lo tiene a fecha 2026-09, así que conserva también un pequeño manejador de clic en el backdrop). No construyas un focus trap propio ni un div con `aria-modal`.