Přeskočit na hlavní obsah
Přístupně.cz
Velikost písma:

Modální okno (nebo dialog) je skvělý pomocník, pokud ho použiješ správně. Můžeš s ním upozornit na důležitou informaci, požádat o potvrzení nebo nabídnout krátký formulář, aniž bys opustil aktuální stránku. Stejně snadno se ale může stát noční můrou, pokud je použito špatně nebo nadměrně.

Kdy vůbec použít modální okno

Modál má smysl, když jde o krátkou, navazující akci: potvrzení destruktivního kroku („Opravdu smazat?“), přihlášení, výběr jedné volby nebo krátký doplňkový formulář. Všude jinde je bezpečnější samostatná stránka – zachováš tok, adresu a historii. WCAG 2.2 sice neříká „kdy modál“, ale požaduje, aby byl ovladatelný klávesnicí, bez pasti a s logickým pořadím fokusu.

Struktura a značení

Dialog nech v DOMu skrytý a při otevření mu dej jasný název i popis. V praxi se osvědčuje role="dialog" a napojení titulku a popisu přes aria-labelledbyaria-describedby. Atribut aria-modal="true" dá čtečkám najevo, že zbytek stránky je dočasně mimo hru.

Doporučení: Tlačítku, které dialog otevírá, přidej aria-haspopup="dialog". Čtečka pak oznámí, že po aktivaci tlačítka se otevře dialog, nikoli nová stránka. Volitelně můžeš přidat i aria-controls="id-dialogu", které vyjadřuje vztah mezi tlačítkem a cílovým dialogem.

<button id="open" aria-haspopup="dialog" aria-controls="dialog">
  Otevřít dialog
</button>

<div id="dialog"
     role="dialog"
     aria-modal="true"
     aria-labelledby="dialog-title"
     aria-describedby="dialog-desc"
     hidden>
  <h2 id="dialog-title" tabindex="-1">Opravdu smazat položku?</h2>
  <p id="dialog-desc">Tuto akci už nepůjde vrátit.</p>
  <button id="confirm">Smazat</button>
  <button id="cancel">Zrušit</button>
</div>

Fokus a ovládání klávesnicí

WCAG 2.2 neurčuje, kam přesně máš po otevření dialogu přesunout fokus. Důležité je, aby uživatel hned pochopil, co se stalo, a měl kontrolu nad situací.

U informačních nebo formulářových dialogů je nejlepší zaměřit viditelný titulek – čtečka hned oznámí název a uživatel ví, kde se nachází. U krátkých potvrzovacích dialogů může být praktičtější zaměřit tlačítko Zrušit nebo Zavřít, aby měl člověk okamžitou možnost modal opustit.

V obou případech zůstává pohyb klávesami Tab/Shift+Tab uvnitř okna, Esc dialog zavře a po zavření se fokus vrátí na prvek, který ho otevřel.

Uzamčení pozadí

Když je dialog otevřený, neměl bys být schopen interagovat se zbytkem stránky. Nejjednodušší je použít atribut inert na kontejner, který obsahuje hlavní obsah, a zároveň zamknout posouvání pomocí body { overflow: hidden; }. Pokud inert není podporován, použij fallback s aria-hidden="true" a nezapomeň ho po zavření odstranit.

Kliknutí mimo a zavírání

Kliknutí mimo dialog může být užitečné, ale jen u informačních modálů. U formulářů nebo destruktivních akcí tím může dojít ke ztrátě dat, proto raději vyžaduj explicitní potvrzení tlačítkem Zrušit nebo Zavřít.

Vícekrokové dialogy

Pokud se dialogy řetězí, snaž se zachovat konzistentní orientaci a návrat fokusu. U delších procesů je ale lepší samostatná stránka. Pokud kroky v modálu opravdu dávají smysl, označ je například „Krok 2 ze 3“ přímo v titulku.

Jak řešit mobilní zobrazení a animace

Dialog se musí vejít na obrazovku bez horizontálního posuvu. Animace by měly respektovat nastavení sníženého pohybu. Pokud má uživatel v systému omezené animace, otevři a zavři dialog bez přechodů.

Testování přístupnosti dialogu

  • Klávesnice: otevři dialog tlačítkem (Enter/mezerník), pohybuj se pomocí Tab/Shift+Tab, zavři ho Esc a ověř, že fokus se vrátil na spouštěcí prvek.
  • Čtečky: v NVDA, JAWS nebo VoiceOver musí čtečka oznámit „dialog“ a jeho titulek, nesmí číst obsah webu na pozadí / za modalem.
  • Mobil: zkontroluj reflow, čitelnost textu a možnost zavřít dialog i bez myši.

Nejčastější chyby

  • Chybí titulek a aria-labelledby.
  • Fokus po otevření zůstává na pozadí nebo se ztrácí.
  • Tab prochází mimo dialog.
  • Esc nefunguje.
  • Kliknutí mimo způsobí ztrátu dat.
  • Pozadí není uzamčené a zůstává interaktivní.

Checklist před nasazením

  • Tlačítko pro otevření má aria-haspopup="dialog" (a volitelně aria-controls).
  • Dialog má viditelný titulek propojený s aria-labelledby.
  • Má nastaveno aria-modal="true" a případně aria-describedby.
  • Při otevření se fokus přesune dovnitř, po zavření zpět na spouštěcí prvek.
  • Tab/Shift+Tab cyklují jen uvnitř; Esc zavírá.
  • Pozadí je uzamčené (inert nebo aria-hidden).
  • Chybové hlášky jsou textové a čitelné pro čtečky.
  • Dialog je responzivní bez horizontálního posuvu.
  • Animace respektují nastavení „snížený pohyb“.
  • Otestováno klávesnicí, NVDA/VoiceOver a na mobilu.

Závěr

Přístupný dialog není složitý, pokud víš, co hlídat. Klíčem je předvídatelnost: čtečka má oznámit, co se děje, fokus se má držet uvnitř a uživatel má mít jistotu, že se dostane zpět tam, odkud přišel. Stačí pár atributů a trocha testování – a modální okna budou fungovat pro všechny.