Normative · ARIA

Ruolo Finestra

dialog

Contrassegna un contenitore come finestra di dialogo modale o non modale. Si consiglia di utilizzare l'elemento nativo <dialog> con showModal() — gestisce gratuitamente il trapping del focus, il top-layer e la chiusura con Escape. Si ricorra a role="dialog" solo quando l'elemento nativo è impossibile da impiegare.

Quando utilizzarlo

Si utilizzi <dialog> aperto tramite .showModal(). L’elemento nativo è supportato da tutti i browser correnti e gestisce autonomamente lo sfondo inerte, il focus trap, la chiusura con Escape, l’hook di stile ::backdrop e il rendering nel top-layer. Consente di risparmiare circa 200 righe di JavaScript fragile.

Si ricorra a role="dialog" su un <div> solo quando:

  • Si supportano browser più vecchi di Chrome 37 / Firefox 98 / Safari 15.4 (improbabile nel 2026).
  • Il design richiede una finestra di dialogo che non può risiedere nel top-layer (caso raro).
  • Si sta correggendo un modal personalizzato inaccessibile durante un refactoring.

Ogni finestra di dialogo DEVE avere un nome accessibile (aria-labelledby che punta a un’intestazione visibile è il pattern più efficace). Le finestre di dialogo modali richiedono inoltre aria-modal="true".

Contratto tastiera + focus

Secondo il pattern dialog (modal) dell’APG:

  • All’apertura, il focus si sposta sul primo elemento focusable all’interno della finestra di dialogo (spesso il pulsante di chiusura o il campo di input principale).
  • Tab e Shift+Tab spostano il focus ESCLUSIVAMENTE all’interno della finestra di dialogo — un «focus trap». Tab dall’ultimo elemento ritorna al primo; Shift+Tab dal primo ritorna all’ultimo.
  • Escape chiude la finestra di dialogo.
  • Alla chiusura, il focus ritorna all’elemento che ha aperto la finestra di dialogo. Salvare e ripristinare il focus è imprescindibile: gli utenti che perdono il proprio punto di riferimento non hanno un’ancora.
  • Il resto della pagina è inert (oppure aria-hidden="true" + non-focusable come fallback) mentre la finestra di dialogo è aperta.

Errori comuni

  • Modal personalizzato senza focus trap. Tab esce dalla finestra di dialogo e si sposta dietro di essa; gli utenti perdono il contesto.
  • Focus non ripristinato sull’elemento trigger alla chiusura. Il successivo Tab atterra sul corpo del documento.
  • Il contenuto in background rimane accessibile via Tab anche se è visivamente nascosto dietro la finestra di dialogo.
  • Nessun nome accessibile. La finestra di dialogo si apre e lo screen reader annuncia solo «dialog».
  • Modal personalizzato senza aria-modal="true" — le tecnologie assistive lo trattano come contenuto inline.
  • Escape chiude la finestra di dialogo, ma questa è renderizzata tramite un portal che perde il focus da tastiera durante l’animazione di chiusura.

Esempio

<!-- Preferito -->
<dialog id="confirm">
  <h2>Delete this draft?</h2>
  <p>This cannot be undone.</p>
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="delete" autofocus>Delete</button>
  </form>
</dialog>
<script>
  document.getElementById('confirm').showModal();
</script>

<!-- Quando <dialog> è impossibile -->
<div role="dialog" aria-modal="true" aria-labelledby="dlgTitle">
  <h2 id="dlgTitle">Edit profile</h2>

</div>