Make accessibility great again: почему скринридер не видит ваши таблицы
Глафира Жур провела небольшое исследование и выяснила, как вернуть таблицам доступность после осенних обновлений Chrome.
![](https://248006.selcdn.ru/main/iblock/9ff/9ffef3ad1d8268e9fe2b603f91964387/749a594aa5e64ec485df94cfb423394c.jpg)
![](https://248006.selcdn.ru/main/iblock/9ff/9ffef3ad1d8268e9fe2b603f91964387/749a594aa5e64ec485df94cfb423394c.jpg)
Кадр: «Сноуден»
![](/upload/setka_images/17233205032022_0bfbd71d4f0eccba0e8ae4942795d0d2d8de6444.jpg)
Глафира Жур
Accessibility Driven Team Lead в SpurIT Google Developer Expert for Web. Организатор @a11yminsk и @MinskCSS/@MinskJS.
Недавно я обнаружила, что скринридер не читает таблицы в Chrome. При этом они выглядят как таблицы, описаны стандартными табличными HTML-тегами, никаких дополнительных стилей к ним не применяли и не меняли роль. Короче говоря, стандартная структура: table > tbody > (tr > td*3)*3.
В чём суть проблемы
![](/upload/setka_images/13274207032022_2229e417950c39bd1ac90259b6c781a232a40430.jpg)
Скриншот: Skillbox Media
Считается, что сделать таблицы доступными можно, соблюдая два основных правила:
1. Задать таблице имя. Например, с помощью <caption> внутри <table> или внешнего лейбла aria-label — специально для программ, читающих с экрана.
2. Задать заголовочную ячейку <th>, чтобы пользователь скринридера понимал, на каком элементе он находится.
Однажды я столкнулась с таким блоком данных:
Open | High |
Close | Low |
Я думала, что он свёрстан при помощи div, поэтому ожидала, что скринридер прочитает ячейки в порядке Open —> Close —> High —> Low. В этом случае первым прозвучал бы div с Open / Close, а потом div с High / Low. Но скринридер прочитал таблицу построчно: Open —> High —> Close —> Low. Получилась какая-то путаница!
Я заглянула в код и увидела, что таблица свёрстана как table — поэтому она и не читалась в ожидаемом порядке. Но возник другой вопрос: почему скринридер не сказал, что читает table? Тогда я проверила роль в Accessibility Tree и нашла role="layouttable"!
![](/upload/setka_images/17250705032022_accf102caaa970ce65d217b9ae9a8e9a57caa67c.jpg)
Скриншот: Skillbox Media
Откуда взялась role = "layouttable" — в спеке не сказано. Сообщений об апдейте Chrome, связанных с этим параметром, я пока тоже не нашла. И в Firefox такого прикола нет — все таблицы обозначаются как role="table".
![](/upload/setka_images/17253305032022_08fda0244b5397e030ee401fd2bea5b24f78a72b.jpg)
Скриншот: Skillbox Media
Как заставить скринридер прочитать таблицу
В результате собственного расследования и благодаря ответу на вопрос в чате Accessibility Community выяснилось, что, если в таблице нет тегов <th>, браузер рассматривает её как layout-таблицу и добавляет role="layouttable". Поэтому скринридер перестаёт её читать как таблицу.
Статья написана на основе треда Глафиры в Twitter.
Кроме того, если у таблицы нет <th>, но атрибутом задана ширина границ (например, border="1") — таблица снова становится table и читается скринридером.
![](/upload/setka_images/17263505032022_6896a8696b8038f4fc8989ab005e4fccc3b90047.jpg)
Скриншот: Skillbox Media
Заметьте: если в структуре HTML-документа не установить <th> или border, но задать значение свойства border в CSS — таблица так и останется layouttable.
Вывод: если хотите, чтобы скринридер правильно читал ваши таблицы в Google Chrome, — не забывайте прописывать <th>.
Ещё для <th> полезно выставлять значение атрибута scope "col", если это заголовок столбца, или "row", если заголовок строки.
На webaim.org работа скринридера с таблицами описывается следующим образом:
«Скринридеры анализируют разметку и структуры таблицы, чтобы „угадать“, является ли она data table или layout table. Поэтому очень важно, чтобы элементы разметки data table, такие как <caption> и <th>, НИКОГДА не использовались в layout table».
![](/upload/setka_images/17272305032022_c7c2d6650fe8dd3125b1541cb39af56649bd56fa.jpg)
Скриншот: Skillbox Media
Как подметил @zavsievich в Twitter, если явно задать таблице без <th> role="table", то Chrome будет говорить скринридеру, что перед ним — таблица. Её дочерние элементы будут читаться как нужно, а скринридер сможет правильно по ней перемещаться.