Proč je klávesová navigace a podpora čteček obrazovky zásadní
Klávesová navigace umožňuje používat web bez myši – pro uživatele s motorickým omezením, pro nevidomé pracující se čtečkou obrazovky (SR, screen reader), ale také v situacích, kdy myš není k dispozici. Čtečky obrazovky převádějí strukturu, role a stav prvků do mluveného výstupu. Společně tak tvoří základ přístupnosti podle standardu WCAG.
Relevantní kritéria WCAG (rychlý přehled)
- 2.1.1 Keyboard (A) – veškeré funkce musejí být dostupné z klávesnice.
- 2.1.2 No Keyboard Trap (A) – uživatel nesmí být v pasti, z níž se nelze klávesnicí dostat.
- 2.1.4 Character Key Shortcuts (A) – jednoklávesové zkratky musí být vypnutelné/změnitelné nebo aktivní jen při fokusu.
- 2.4.1 Bypass Blocks (A) – možnost přeskočit opakující se bloky (např. „Přeskočit na obsah“).
- 2.4.3 Focus Order (A) – logická posloupnost fokusu.
- 2.4.7 Focus Visible (AA) – zřetelný indikátor fokusu.
- 1.3.1 Info and Relationships (A) – sémantika musí vyjadřovat vztahy (nadpisy, seznamy, form labels).
- 4.1.2 Name, Role, Value (A) – komponenty musí mít správné jméno, roli a hodnotu.
- 4.1.3 Status Messages (AA) – důležité statusy musí být oznamovány bez přesunu fokusu.
Základy klávesové navigace
- Tab cyklus –
TabaShift+Tabpřechází mezi fokusovatelnými prvky v logickém pořadí DOM a vizuálního rozvržení. - Šipky – pro roving tabindex uvnitř složených widgetů (menu, tablist, radiogroup).
- Enter/Space – aktivace tlačítek a odkazů;
Spacepřepínácheckbox. - Esc – ruší modální dialogy, popover a další přechodné vrstvy.
Fokusovatelnost a pořadí fokusu
Fokusovatelnými prvky jsou primárně nativní interaktivní elementy (<a href>, <button>, <input>, <select>, <textarea>, prvky s contenteditable a sémantickými rolemi). Manuální přidávání fokusu (tabindex="0") používejte uvážlivě a vyhněte se tabindex > 0, který rozbíjí přirozenou posloupnost.
- Pořadí fokusu by mělo odrážet vizuální čtení zleva doprava, shora dolů.
- Skryté prvky (
display:none,hidden,aria-hidden="true") nesmí dostat fokus. - U modálních dialogů omezte tab do pasti uvnitř dialogu (focus trap) a při zavření vraťte fokus na spouštěcí prvek.
Viditelný indikátor fokusu
Viditelný fokus je nutný pro klávesnicové uživatele i pro uživatele s nízkým zrakem. Nikdy neodstraňujte obrys (outline: none) bez náhrady. Preferujte systémové focus-visible styly:
/* Použijte :focus-visible pro klávesnici, ne pro myš */ :where(a, button, input, select, textarea, [tabindex]):focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
Skip odkazy a landmarky
„Přeskočit na obsah“ je první fokusovatelný odkaz na stránce, který vede k hlavnímu obsahu. Pro strukturaci použijte landmark elementy/role: <header>/banner, <nav>/navigation, <main>/main, <aside>/complementary, <footer>/contentinfo. Čtečky obrazovky umožní rychlý skok mezi landmarky.
<a class="skip-link" href="#main">Přeskočit na obsah</a> <main id="main" tabindex="-1">...</main> /* .skip-link by měl být viditelný při fokusu */
Semantika, role a ARIA
Preferujte nativní HTML. Kde to nejde, dodejte ARIA: role, aria-label/aria-labelledby, aria-expanded, aria-controls, aria-checked, atd. Dodržujte pravidlo „ARIA je poslední možnost“. Nesprávná ARIA je horší než žádná.
- Name – programový název: text v tlačítku,
label,aria-label. - Role – co to je:
button,link,dialog,tab,menuitem… - Value/State – stav/hodnota:
aria-pressed,aria-selected,aria-expanded.
Vzor: roving tabindex pro seznam voleb
U widgetů s jedním fokusem a více položkami (např. horizontální menu) použijte roving tabindex: pouze aktivní položka má tabindex="0", ostatní -1; šipky přesouvají fokus.
<ul role="menubar"> <li role="menuitem"><button tabindex="0">Domů</button></li> <li role="menuitem"><button tabindex="-1">Služby</button></li> <li role="menuitem"><button tabindex="-1">Kontakt</button></li> </ul> <script> const items = Array.from(document.querySelectorAll('[role="menuitem"] > button')); function setActive(i){ items.forEach((b, j) => { b.tabIndex = (i===j?0:-1); }); items[i].focus();} items.forEach((btn, i) => btn.addEventListener('keydown', e => { if (e.key === 'ArrowRight') { e.preventDefault(); setActive((i+1)%items.length); } if (e.key === 'ArrowLeft') { e.preventDefault(); setActive((i-1+items.length)%items.length); } })); </script>
Přístupné modální dialogy
- Použijte
role="dialog"nebo nativní<dialog>, definujtearia-modal="true"a programový název přesaria-labelledby/aria-label. - Při otevření přesuňte fokus na první smysluplný prvek v dialogu, při zavření vraťte na spouštěč.
- Zachyťte
Tab/Shift+Tabuvnitř dialogu (focus trap) a reagujte naEsc. - Zbytek stránky označte jako neinteraktivní (
inertna kontejnerech nebo správa přesaria-hidden), aby SR nečetla obsah na pozadí.
Čtečky obrazovky: jak pracují a jak testovat
Hlavní čtečky: NVDA a JAWS (Windows), VoiceOver (macOS/iOS), TalkBack (Android). SR nabízejí „virtuální kurzor“, který prochází logicky čitelným obsahem. Důležité zkratky:
- Nadpisy – navigace po úrovních (např. NVDA:
H/Shift+H), proto používejte smysluplnou hierarchiih1–h6. - Landmarky – skok mezi rolemi (
Rv NVDA), proto definujtemain,navigation,search… - Formuláře – NVDA
Fpro formulářové prvky; každý musí mít asociovaný<label for>neboaria-labelledby. - Seznamy a tabulky – SR čte počty položek/řádků, u tabulek dbejte na záhlaví
<th scope>.
Formuláře: názvy, chybové stavy a instrukce
- Každé pole musí mít programový název (label). Nepoužívejte jen placeholder jako náhradu.
- Chyby oznamte textově v blízkosti polí a programově pomocí
aria-describedby. Interaktivně oznamujte pomocíaria-live(viz níže). - Seskupujte související volby pomocí
<fieldset>a<legend>.
Status zprávy a živé oblasti
Pro nenápadná oznámení bez přesunu fokusu použijte aria-live nebo vhodné role (status, alert):
<div id="cart-status" role="status" aria-live="polite"></div> <script> function addedToCart(name){ document.getElementById('cart-status').textContent = `${name} přidán do košíku.`; } </script>
Klávesové zkratky a konflikty
Jednoklávesové zkratky mohou kolidovat se SR nebo s prohlížečem. Pokud je zavádíte:
- umožněte je vypnout nebo změnit (WCAG 2.1.4),
- omezte aktivitu pouze při fokusu na konkrétním prvku,
- vyhněte se přetěžování písmen bez modifikátorů.
Vlastní komponenty vs. nativní prvky
Nativní prvky mají vestavěné chování, sémantiku i klávesové mapy. Vlastní komponenty (např. pseudo-tlačítko v <div>) vyžadují kompletní doplnění: role, klávesové ovládání, stavy, oznámení.
<!-- Špatně: --> <div class="btn" onclick="doX()">Uložit</div>
Interakční vzory a doporučení pro design
- Velké klikací plochy a dostatečný kontrast fokusu.
- Logická hierarchie nadpisů – žádné skoky z
h2rovnou nah5. - Konzistence – stejné komponenty mají stejné ovládání napříč aplikací.
- Viditelné stavy – hover, focus, active, selected; oznámené i SR přes ARIA stavy.
- Respekt k pohybovým preferencím – redukujte animace pro
prefers-reduced-motion, aby fokus „neutíkal“.
Testovací postup pro klávesnici
- Odpojte myš nebo ji prostě nepoužívejte.
- Odpočkejte, kde se objeví fokus a zda je vždy zřetelný.
- Zkontrolujte, že všechny funkce jsou dostupné pomocí
Tab, šipek,Enter,SpaceaEsc. - Ověřte, že vás žádný prvek „neuvězní“ (bez pastí).
- Prověřte logiku pořadí – odpovídá vizuálnímu uspořádání a významu?
Testovací postup pro čtečky obrazovky
- Zapněte SR (např. NVDA/JAWS/VoiceOver) a projděte stránku lineárně (virtuální kurzor).
- Vyzkoušejte navigaci nadpisy, landmarky a formulářovými prvky.
- Ověřte, že každý interaktivní prvek má správné jméno, roli a stav.
- Zkontrolujte oznámení statusů (aria-live) bez přesunu fokusu.
- Projděte klíčové scénáře: otevření dialogu, přidání do košíku, filtrování, změna záložky.
Časté chyby a jak se jim vyhnout
- Odstranění focus outline bez náhrady – vždy poskytněte viditelný fokus.
- Použití
tabindex>0– rozbíjí pořadí; používejte jen0nebo-1. - Interaktivní role na neinteraktivních prvcích bez klávesové logiky.
- Neoznačené ikony – dodejte textový název (např.
aria-label="Hledat"). - Chybějící návrat fokusu po zavření modalu nebo po intra-stránkové navigaci.
- Živé aktualizace beze slovního oznámení SR.
Specifika pro aplikace s bohatým JavaScriptem (SPA)
- Při změně pohledu (routing bez reloadu) přesunout fokus na nadpis nového obsahu (
tabindex="-1"+ programovéfocus()). - U dynamických seznamů a filtrů oznamovat změny počtu výsledků (
role="status"). - Aktualizovat
document.titlea/nebo použítaria-livepro významné změny.
Mezinárodní a mobilní hlediska
- Na mobilu je klíčová podpora SR gest (VoiceOver, TalkBack) – správná sémantika se promítá do rotorů/navigace.
- Vyhněte se gestům bez alternativy – nabídněte tlačítka a klávesové ekvivalenty i pro desktop.
- Správně nastavte jazyk dokumentu a oblastí (
<html lang="cs">, případnělangna úrovni komponent).
Doporučený proces přístupnosti v týmu
- Definice standardů – společná knihovna komponent s dokumentovanými rolemi a klávesovou mapou.
- Linting a CI – automatické kontroly (axe, eslint-plugin-jsx-a11y) a vizuální testy fokusu.
- Design review – kontrola viditelnosti fokusu, kontrastů a pořadí tabulace již v prototypu.
- Manuální testy – klávesnice + SR na hlavních platformách před vydáním.
- Regrese – při změně komponent spouštět zkrácený SR/keyboard test set.
Kontrolní seznam (shrnutí)
- Vše lze ovládat klávesnicí, bez pastí a s logickým pořadím.
- Fokus je vždy jasně viditelný (
:focus-visiblestyly). - Správná sémantika, role a programové názvy; žádné falešné „div-buttony“.
- Skip link a landmarky pro rychlé přeskočení bloků.
- Dialogy jsou pojmenované, mají focus trap, vrací fokus po zavření a nečtou pozadí.
- Živé změny a chyby jsou oznamovány přes
aria-live/role="status". - Klávesové zkratky jsou bezpečné a konfigurovatelné.
- Testováno s minimálně jednou SR na desktopu a jednou na mobilu.
Závěr
Klávesová navigace a čtečky obrazovky nejsou doplňky „na konec“, ale základní vrstva použitelnosti. Kombinací nativního HTML, promyšleného pořadí fokusu, viditelných stavů a přiměřené ARIA dosáhnete webu, který je přístupný, robustní a příjemný všem uživatelům – nejen těm se SR.