Skip to main content
UI Patterns 65% faalt

Dialoog / modal

Focusvasthouding binnenin, Escape om te sluiten, focus keert terug naar trigger bij sluiting. Gebruik <dialog> of role="dialog" + aria-modal="true". Een van de meest kapotte patronen.

In gewone taal

Pop-up windows must keep keyboard focus inside while open, close with the Escape key, and return you to where you started.

Het native HTML

-element met showModal() regelt de meeste toegankelijkheidsvereisten automatisch: focusvasthouding, Escape om te sluiten, achtergrond-inertness en juiste rol. Het is de aanbevolen aanpak boven aangepaste ARIA-implementaties.

Als je een aangepaste modal moet gebruiken: stel role="dialog" + aria-modal="true" in, houd focus vast met een focus-trap bibliotheek, verwerk Escape, en retourneer focus naar het triggerelement bij sluiting.

Waarom dit belangrijk is

Modale dialogen falen op ongeveer 65% van de sites die ze gebruiken. Zonder goed focusbeheer tabben toetsenbordgebruikers achter de modal naar onzichtbare inhoud. Zonder Escape-ondersteuning kunnen ze het niet sluiten. Zonder focusterugkeer verliezen ze hun plek na sluiting.

Hoe te detecteren

Snelle controle

Open de modal met toetsenbord (Enter/Spatie). Kun je door alle elementen binnenin tabben? Wrapt Tab binnen de modal? Sluit Escape het? Keert na sluiting de focus terug naar de trigger? Kun je interactie hebben met inhoud achter de modal?

Hoe op te lossen

<!-- Modern: use native <dialog> element -->
<button id="open-btn">Open</button>
<dialog id="my-dialog">
  <h2>Dialog title</h2>
  <p>Content here.</p>
  <button autofocus>Confirm</button>
  <button id="close-btn">Cancel</button>
</dialog>

<script>
const dialog = document.getElementById('my-dialog');
const openBtn = document.getElementById('open-btn');
const closeBtn = document.getElementById('close-btn');

openBtn.addEventListener('click', () => dialog.showModal());
closeBtn.addEventListener('click', () => dialog.close());

dialog.addEventListener('close', () => openBtn.focus());
</script>

<!-- The <dialog> element handles: -->
<!-- ✓ Focus trapping -->
<!-- ✓ Escape to close -->
<!-- ✓ role="dialog" -->
<!-- ✓ Background inert -->