Дърво на достъпността
Също: a11y tree, accessibility object model, AOM
Вътрешната структура от данни, която браузърите и операционните системи изграждат от DOM — съпоставяща всеки елемент с роля, име, състояние и взаимовръзки. Именно тя обхождат екранните четци и другите помощни технологии.
Дървото на достъпността е структурата от данни на ниво операционна система, която екранните четци и другите помощни технологии реално консумират. Когато се отвори страница в браузър, той изгражда две дървета: DOM дървото (стандартната HTML йерархия) и дървото на достъпността — успоредна структура, производна на DOM, но съдържаща метаданни за достъпност.
Разбирането на дървото на достъпността обяснява около 80% от иначе объркващото поведение на ARIA, екранните четци и сесиите за отстраняване на грешки от рода на „защо не се обявява?”.
Какво съдържа
Всеки възел в дървото на достъпността притежава:
- Роля — какво представлява елементът: бутон, връзка,
заглавие, навигация, диалог. Определя се от типа HTML елемент
или от явно зададен ARIA атрибут
role="...". - Име — как се нарича елементът. Произлиза от текста на
етикета, атрибута
alt,aria-label,aria-labelledbyили изчисленото текстово съдържание. - Описание — допълнителен контекст. Произлиза от
aria-describedbyили атрибутиtitle. - Състояние — текущо състояние: натиснат, разгънат, отметнат,
зает. Определя се от HTML атрибути (
disabled,required) или ARIA (aria-pressed,aria-expanded). - Свойства — взаимовръзки и метаданни:
aria-controls,aria-owns,aria-haspopup.
Екранните четци обхождат това дърво и обявяват всеки възел въз основа на тези полета. Навигацията с Tab и стрелките минава през дървото на достъпността, а не през DOM.
Защо чисто визуалното съдържание изчезва
<div onclick="..."> оформен като бутон няма роля в дървото на
достъпността — браузърът вижда обикновен <div> и го записва като
role="generic" (практически невидим за помощните технологии).
Манипулаторът onclick не се пренася в дървото на достъпността,
защото то отразява само това, което браузърът извежда като роля
на елемента от неговия HTML тип.
Затова семантичният HTML има значение на най-фундаментално ниво: не заради стил или конвенция, а защото семантичните HTML елементи автоматично попълват дървото на достъпността с правилните роли. Несемантичната маркировка създава „div-soup” дърво, от което екранните четци не могат да извлекат смисъл.
Ролята на ARIA в дървото
ARIA съществува именно за да попълва дървото на достъпността в
случаите, когато нативният HTML няма подходящ елемент. role="combobox"
казва на браузъра да постави combobox възел в дървото за елемент,
който иначе би се появил като generic. aria-expanded="true" задава
свойство за състояние на този възел.
ARIA НЕ променя DOM. Тя променя това, което браузърът записва в дървото на достъпността.
Как да се инспектира
Инструментите за разработчици в браузърите вече предоставят пряк достъп до дървото на достъпността:
- Chrome / Edge DevTools — панел Elements → раздел Accessibility (дясна колона) показва изчислените свойства за достъпност на избрания възел. Превключвателят „Full-page accessibility tree” (флаг в Chrome при някои версии) извежда дървото като странична лента.
- Firefox DevTools — панел Accessibility (икона в лентата с инструменти) показва специализиран изглед на дървото на достъпността, подобен на изгледа Elements, но в термините на дървото.
- Safari Web Inspector — разделите Audit / Accessibility предлагат сравнима инспекция.
Когато дървото на достъпността е видимо, въпросът „защо не се обявява?” може да получи емпиричен отговор. Почти винаги той е: възелът в дървото има различна роля от очакваната, или името му е празно, или състоянието му е грешно.
Защо „дърво на достъпността” е по-добрият мисловен модел от „ARIA”
Инженерите, които учат ARIA без да разбират дървото на достъпността, в крайна сметка разпръскват ARIA атрибути с надеждата, че екранните четци ще ги вземат предвид. Инженерите, разбиращи дървото на достъпността, знаят, че задачата на ARIA е да записва конкретни полета в конкретни възли на дървото, и че директната инспекция на дървото е по-бърза от гадаенето.