Responzivní přístupné tabulky
Tabulka se dvěma sloupci se na úzkou obrazovku vejde bez potíží. Tabulka s pěti nebo deseti sloupci na mobilu buď přeteče mimo obrazovku, nebo donutí uživatele ke scrollování do stran, a to samé se stane i na širokém displeji, jakmile si uživatel zvětší písmo o desítky procent. Řešení není jen zmenšit písmo nebo nechat tabulku přetékat, ale přeskládat její vizuální podobu, aniž se změní skutečný obsah a struktura, kterou z ní čte odečítač obrazovky.
1. Kdy tabulku rozložit na karty a kdy nechat scrollovat
WCAG 1.4.10 (Reflow) požaduje, aby šlo obsah přečíst bez scrollování ve dvou směrech najednou, tedy nahoru dolů i zároveň doleva doprava. Výjimku samo WCAG povoluje jen tam, kde je dvourozměrné uspořádání pro pochopení obsahu opravdu nezbytné, typicky u rozsáhlé srovnávací tabulky nebo mapy, kde by rozpad na jeden sloupec smysl obsahu zničil.
U běžné tabulky, jako je ceník, přehled objednávek nebo rozpis odjezdů, dvourozměrné uspořádání nezbytné není. Každý řádek dává smysl i sám o sobě, vypsaný pod sebou jako dvojice popisek a hodnota. Právě tenhle typ tabulky by se měl na úzké obrazovce nebo při velkém zvětšení textu přeskládat na jeden sloupec, místo aby nutil ke scrollování do stran.
2. Tabulka rozložená jako karty
Řádek tabulky se na úzké obrazovce vykreslí jako samostatná karta, buňky pod sebou, každá se svým popiskem z atributu data-label:
<table>
<caption>Rozpis odjezdů</caption>
<thead>
<tr>
<th scope="col">Spoj</th>
<th scope="col">Odjezd</th>
<th scope="col">Nástupiště</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Spoj">R 123</td>
<td data-label="Odjezd">14:32</td>
<td data-label="Nástupiště">2</td>
</tr>
</tbody>
</table>
@media (max-width: 40em) {
table, thead, tbody, tr, th, td {
display: block;
}
thead {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
tr {
margin-block-end: 1em;
border-block-end: 1px solid;
}
td::before {
content: attr(data-label) ": ";
font-weight: bold;
}
}
Záhlaví thead při rozpadu na karty zmizí z vizuálního zobrazení, ale zůstává v DOM, takže z něj popisky jednotlivých buněk pořád čerpá data-label, i kdyby se k tabulce odečítač dostal jinak než přes vizuální rozpad.
3. Past: změna display odebere roli tabulky
Tohle bývá to hlavní místo, kde se tenhle vzor pokazí. Jakmile se display na <table>, <tr> nebo <td> změní na cokoli jiného, než jsou výchozí tabulkové hodnoty, Chrome i Firefox přestanou danému prvku přiřazovat jeho vestavěnou ARIA roli table, row nebo cell. Odečítač pak nedostane informaci, že je v tabulce a kolikátý je právě řádek, protože mu CSS tuhle informaci tiše vzalo spolu se změnou vzhledu.
Oprava je jednoduchá, jen se na ni snadno zapomíná: role dopsat ručně, přesně podle toho, co display odebral.
<table role="table">
<tbody>
<tr role="row">
<td role="cell" data-label="Spoj">R 123</td>
</tr>
</tbody>
</table>
S výslovnou rolí zůstane tabulka tabulkou pro odečítač bez ohledu na to, jak moc se vzhled mezi širokou a úzkou obrazovkou liší.
Proč to takhle je
- Vizuální rozpad na karty a skutečná struktura dat jsou dvě různé věci, protože reflow mění jen to první a obsah tabulky zůstává úplně stejný.
- Skrytí
theadnamísto jeho smazání zachovává popisky sloupců v DOM prodata-label, i když se vizuálně neukazuje. - Role se musí dopsat ručně, protože prohlížeč je po změně
displaysám nedoplní, takže by bez nich odečítač slyšel jen sled samostatných bloků textu, ne tabulku s řádky a sloupci.
Pravidla
- WCAG 1.4.10 (Reflow) říká, že obsah nesmí vyžadovat scrollování ve dvou směrech najednou, pokud dvourozměrné uspořádání není pro pochopení obsahu nezbytné.
- WCAG 1.3.1 (Info a vztahy) vyžaduje, aby vztah mezi popiskem sloupce a hodnotou buňky zůstal zachovaný i po změně vizuálního rozvržení.