ARIA: atributy přístupnosti v HTML

Co je WAI-ARIA a proč patří mezi základy moderního webu

WAI-ARIA (Accessible Rich Internet Applications) je soubor HTML atributů definovaný konsorciem W3C, který doplňuje sémantiku a interakce webových komponent tak, aby byly přístupné uživatelům asistivních technologií (čtečky obrazovky, alternativní vstupy). ARIA nevytváří vizuální prvky, ale „říká“ strojům, co prvky jsou a co právě dělají. V době SPA aplikací, vlastních komponent a AI/LLM indexace je ARIA klíčová pro přístupnost (a11y), SEO i AIO/AEO – pomáhá vyhledávačům a modelům pochopit strukturu a stavy uživatelského rozhraní.

Zásady: kdy ARIA používat a kdy ne

  • Přednost má nativní HTML. Pokud existuje sémantický prvek (button, nav, header, ul/li, table, form), použijte ho. ARIA je doplněk, nikoliv náhrada.
  • ARIA by neměla měnit vizuální chování. Ovládání klávesnicí a fokus řešte v JS/CSS, ARIA pouze popisuje roli a stav.
  • „No ARIA is better than bad ARIA“. Špatné stavy, chybné reference nebo nesoulad rolí škodí více než žádná ARIA.
  • Konzistence stavů. Atributy jako aria-expanded, aria-selected, aria-checked musí odrážet skutečný stav komponenty.

Stavebnice ARIA: role, properties, states

ARIA se dělí do tří hlavních skupin:

  • Role (např. role="button", role="dialog", role="navigation") – definují typ widgetu nebo landmarku.
  • Properties (např. aria-labelledby, aria-describedby, aria-owns) – stabilní vlastnosti a vztahy.
  • States (např. aria-expanded, aria-checked, aria-busy) – měnící se stavy během interakcí.

Landmark role: kostra stránky pro rychlou navigaci

Landmarky umožňují skokovou navigaci čtečkami obrazovky a zároveň pomáhají vyhledávačům a LLM pochopit layout:

  • role="banner" – hlavička webu (obvykle na <header>).
  • role="navigation" – hlavní navigace (často <nav>).
  • role="main" – hlavní obsah (obvykle <main>).
  • role="complementary" – doplňkové panely (sidebar).
  • role="contentinfo" – patička (na <footer>).
  • role="search" – vyhledávací formulář.

Používejte nativní prvky (header, nav, main, aside, footer), které již landmark roli implicitně nesou. ARIA roli přidávejte jen když nepoužíváte nativní element nebo potřebujete upřesnit význam.

Názvy a popisy: aria-label, aria-labelledby, aria-describedby

  • Viditelný název > aria-label. Pokud prvek již má viditelný text (např. obsah tlačítka), ten je jeho accessible name. aria-label používejte u ikon bez textu.
  • aria-labelledby váže název na jiný element dle id a má vyšší prioritu než aria-label.
  • aria-describedby poskytuje doplňující popis (tooltip, nápověda), který se čte po názvu.

Příklad ikonického tlačítka bez textu:

<button aria-label="Otevřít menu"></button>

Interaktivní widgety: chování, stavy a klávesnice

Při vlastních komponentách je nutné sladit roli, stav i ovladatelnost klávesnicí:

  • Button: role="button", aktivace Enter i Space, fokus přes tabindex="0" (pokud to není nativní <button>).
  • Disclosure/Accordion: ovládací prvek s aria-expanded="true|false" a cíl s aria-hidden nebo řízeným zobrazením; propojení přes aria-controls.
  • Tabs: role="tablist" obsahuje role="tab" s aria-selected, panely mají role="tabpanel" a jsou navázány přes aria-controls/aria-labelledby. Šipky mění fokus mezi taby.
  • Menu/menubar a listbox: respektujte definované klávesové vzory (šipky, Home/End, Enter/Escape).

Živé oblasti a dynamický obsah: aria-live, aria-busy

Při asynchronních akcích oznamujte změny:

  • aria-live="polite|assertive" – čtečky oznámí novinky v oblasti; polite čeká na vhodný moment, assertive přeruší čtení.
  • aria-busy="true" – signalizuje načítání; nastavte zpět na false, když je obsah připravený.
  • role="status" nebo role="alert" – krátké zprávy o úspěchu/chybě.

Skrytí a prezentace: aria-hidden, inert a správa fokusu

  • aria-hidden="true" odstraní prvek ze stromu přístupnosti, ale nezablokuje fokus. U modalů preferujte inert na okolí, aby se zablokovala interakce i fokus.
  • Při otevření dialogu přesuňte fokus dovnitř a po uzavření vraťte na spouštěč.
  • Skryté dekorace (SVG, ikonové fonty) označte aria-hidden="true" nebo role="img" aria-label="..." s významem.

Obrázky a grafika: role=“img“, alt a komplexní vizualizace

  • Pro <img> používejte alt. U dekorativní grafiky zvolte prázdný alt="" a zvažte aria-hidden="true".
  • Pro nestandardní grafiky (SVG, canvas) použijte role="img" a název přes aria-label nebo aria-labelledby.
  • Komplexní grafy zpřístupněte krátkým názvem a delším popisem vázaným přes aria-describedby, případně nabídněte datovou tabulku.

Formuláře: chyby, nápovědy a povinná pole

  • Propojte label s polem přes <label for="id"> a id. Pokud label chybí, použijte aria-label.
  • Nápovědu připojte přes aria-describedby="id-popisu".
  • Chyby signalizujte aria-invalid="true" a dynamickou chybovou hlášku v oblasti s role="alert" nebo aria-live.
  • Povinnost pole indikujte vizuálně i programově přes aria-required="true" (u vlastních widgetů).

Dialogy a upozornění: role=“dialog“ a role=“alertdialog“

  • Kontejner má role="dialog" a název přes aria-labelledby (nebo aria-label).
  • U kritických potvrzení použijte role="alertdialog" (intenzivnější pozornost).
  • Uzamkněte pozadí (inert nebo „focus trap“) a zajistěte klávesu Escape pro zavření.

Navigační prvky: breadcrumbs, pagination, skip links

  • Označte drobečkovou navigaci nav s aria-label="Drobečková navigace" podle jazyka; odkazy v seznamu.
  • Paginaci označte nav s aria-label="Stránkování"; aktuální stránka má aria-current="page".
  • Odkaz „Skip to content“ umístěte na začátek a cílový prvek označte id; hlavní obsah nechť má role="main" nebo <main>.

Tabulky, seznamy a struktury: respektujte nativní sémantiku

Pro datové tabulky používejte <table> s <thead>, <tbody>, <th scope="col|row">. Vyhýbejte se ručnímu skládání tabulek z div s ARIA rolemi, pokud to není nezbytné.

ARIA a výkon LLM/SEO: proč to prospívá AIO/AEO

  • Jednoznačná struktura. Landmarky a správné názvy prvků zlepšují pochopení informační architektury modely a crawlerem.
  • Přesné vztahy. Vztahy aria-labelledby/aria-describedby doplňují kontext (např. k tlačítkům, panelům, kartám), což pomáhá extrahovat smysluplné odpovědi.
  • Bohaté stavy UI. Správně aktualizované stavy (aria-expanded, aria-selected) vedou k lepšímu pochopení interaktivity a viditelnosti obsahu.
  • Nižší chybovost parsování. Konzistentní ARIA snižuje šum a anomálie v datech používaných pro indexaci a trénink.

Antivzory: čemu se vyhnout

  • Falešné tlačítko z div s role="button" bez podpory Enter/Space a bez tabindex.
  • Konflikt role a elementu. Např. <button role="link"> mate čtečky; použijte správný element.
  • Nesprávné živé oblasti. Zbytečné aria-live="assertive" ruší uživatele.
  • Skrytí obsahu pouze vizuálně. display:none bez ohledu na stav ARIA může čtečku zmást; slaďte vizuální a accessibility stav.
  • Neplatné reference. aria-labelledby="neexistuje" nebo duplicity id.

Testování a validace: praktický postup

  1. Rychlý audit klávesnicí. Projeďte celé UI jen s Tab/Shift+Tab, Enter, Space, šipkami. Fokus musí být viditelný.
  2. Semantická kontrola. Ověřte landmarky (banner, navigation, main, complementary, contentinfo, search).
  3. Stavy v akci. Sledujte, zda se aria-expanded, aria-selected, aria-busy při interakci mění.
  4. Automatizované nástroje. Spusťte lintry a audity (např. axe, Lighthouse, HTML validator) a opravte chyby s vysokou prioritou.
  5. Čtečka obrazovky. Otestujte minimálně v jednom prostředí (NVDA/JAWS/VoiceOver) základní scénáře.

Mini-vzory: zhuštěné příklady

Rozbalovací menu (disclosure):

<button aria-expanded="false" aria-controls="sekce-menu" id="tlacitko-menu">Menu</button>

<div id="sekce-menu" role="region" aria-labelledby="tlacitko-menu" hidden>...navigace...</div>

Při otevření odstraňte hidden a nastavte aria-expanded="true".

Záložky (tabs):

<div role="tablist" aria-label="Sekce">
  <button role="tab" id="tab-1" aria-controls="panel-1" aria-selected="true">Přehled</button>
  <button role="tab" id="tab-2" aria-controls="panel-2" aria-selected="false">Detaily</button>
</div>

<section role="tabpanel" id="panel-1" aria-labelledby="tab-1">...</section>
<section role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>...</section>

Mezijazyčnost a lokalizace

  • Nastavte jazyk dokumentu přes <html lang="sk">; čtečky podle toho volí syntézu řeči.
  • ARIA štítky pište v jazyce obsahu. U vícejazyčných sekcí používejte lang na vnořených prvcích.

ARIA a design systém: udržitelná implementace

  • Zaveďte knihovnu komponent s jednotnou sémantikou (role, stavy, názvy, klávesnice).
  • Každý komponent dokumentujte: jaké ARIA atributy používá, kdy a jak se mění, jaké má klávesové zkratky.
  • Přidejte unit/e2e testy na stavy a dostupnost (fokus, tab order, live regions).

Checklist pro release

  • Nativní HTML tam, kde to jde; ARIA jen doplňuje.
  • Viditelný fokus