Кратко
СкопированоСвойство виджета из WAI-ARIA для указания места элементов в их иерархии. Это важно для заголовков, древовидных и ассоциативных списков и других похожих элементов.
aria
помогает браузерам и вспомогательным технологиям рассказать об уровнях элементов, когда не можете передать их иерархию с помощью чистого HTML.
Пример
Скопировано<span role="heading" aria-level="1"> Гайвань</span><p> Традиционная китайская посуда для заваривания чая. Дословно переводится как «чаша с крышкой».</p><p> Cостоит из трёх частей: крышки, чаши и блюдца. В чашу кладут чайные листья для заварки. Крышка сохраняет тепло и усиливает аромат чая. Блюдце используют как подставку для чаши, чтобы было удобнее разливать заваренный чай по пиалам.</p><p> Самые распространённые материалы, из которых делают гайвани, — фарфор и керамика.</p>
<span role="heading" aria-level="1" > Гайвань </span> <p> Традиционная китайская посуда для заваривания чая. Дословно переводится как «чаша с крышкой». </p> <p> Cостоит из трёх частей: крышки, чаши и блюдца. В чашу кладут чайные листья для заварки. Крышка сохраняет тепло и усиливает аромат чая. Блюдце используют как подставку для чаши, чтобы было удобнее разливать заваренный чай по пиалам. </p> <p> Самые распространённые материалы, из которых делают гайвани, — фарфор и керамика. </p>
Скринридеры прочтут код примерно так: «Гайвань, заголовок первого уровня».
Как пишется
СкопированоДобавьте к нужному элементу aria
с положительным числом от 1
и больше. Например, aria
. Исключение — кастомные заголовки с ролью heading
. Их максимальный уровень не может быть выше 6
.
aria
можно использовать для элементов со следующими явными ARIA-ролями:
heading
(по умолчанию есть у<h1>
–<h6>
).row
(уже встроена в<tr>
).treeitem
.associationlistitemkey
(есть у<dt>
).comment
.
Чем ниже элемент в иерархии или глубже вложен в другие, тем выше его уровень. Обычно во вложенных элементах уровень первого элемента, родителя, не указывают. Отсчёт начинается с первого вложенного элемента — ребёнка.
Пример со вложенными элементами.
<!-- Нерабочий код ❌--><div> Первый уровень <span aria-level="2"> Второй уровень </span> <span aria-level="2"> Второй уровень <span aria-level="3"> Третий уровень <span aria-level="4"> Четвёртый уровень </span> <span aria-level="4"> Четвёртый уровень </span> </span> </span></div>
<!-- Нерабочий код ❌--> <div> Первый уровень <span aria-level="2"> Второй уровень </span> <span aria-level="2"> Второй уровень <span aria-level="3"> Третий уровень <span aria-level="4"> Четвёртый уровень </span> <span aria-level="4"> Четвёртый уровень </span> </span> </span> </div>
Пример с отдельными элементами, когда важно показать их иерархию.
<!-- Нерабочий код ❌--><span aria-level="1"> Первый уровень</span><span aria-level="2"> Второй уровень</span><span aria-level="3"> Третий уровень</span><span aria-level="4"> Четвёртый уровень</span><span aria-level="2"> Второй уровень</span><span aria-level="3"> Третий уровень</span>
<!-- Нерабочий код ❌--> <span aria-level="1"> Первый уровень </span> <span aria-level="2"> Второй уровень </span> <span aria-level="3"> Третий уровень </span> <span aria-level="4"> Четвёртый уровень </span> <span aria-level="2"> Второй уровень </span> <span aria-level="3"> Третий уровень </span>
Заголовки
СкопированоИспользуйте для заголовков теги <h1>
–<h6>
. У них по умолчанию есть свойство aria
. Когда по крайне важной причине верстаете кастомные заголовки, учитывайте несколько особенностей поведения aria
.
Заголовок с ролью heading
без aria
автоматически получает второй уровень.
<span role="heading"> Гайвань</span>
<span role="heading" > Гайвань </span>
Проверим в инструменте разработчика в Chrome. Браузер вычисляет второй уровень в строке со свойством «Level».
Пытливые умы могут добавить заголовок выше шестого уровня, чтобы перехитрить браузеры. Будьте готовы к тому, что эксперимент закончится неудачей. Например, здесь пытаемся убедить браузер в существовании заголовка десятого уровня:
<!-- Не делайте так ❌--><span role="heading" aria-level="10"> Гайвань</span>
<!-- Не делайте так ❌--> <span role="heading" aria-level="10" > Гайвань </span>
Некоторые старые браузеры понимали значения до 9
. Новые браузеры всегда вычисляют 2
, когда уровень heading
выше шестого. Так что десятый уровень aria
из примера станет вторым.
Лучше не вкладывать заголовки друг в друга, чтобы сверстать подзаголовки. Ради интереса попробуем вложить в один заголовок с aria
другой с aria
.
<!-- Не делайте так ❌--><span role="heading" aria-level="1"> Гайвань <span role="heading" aria-level="2" > История </span></span>
<!-- Не делайте так ❌--> <span role="heading" aria-level="1" > Гайвань <span role="heading" aria-level="2" > История </span> </span>
Браузеры решат, что это два отдельных заголовка первого и второго уровня.
Скринридеры вообще запутаются. Например, NVDA скажет: «Гайвань, заголовок первого уровня. История, заголовок первого уровня, заголовок второго уровня». В списке всех заголовков страницы будет правильная иерархия, но повторятся названия вложенных. Получается, что название заголовка первого уровня — «ГайваньИстория», а второго — «История».
Древовидные списки
СкопированоТип списков, в которых видна иерархия элементов. Они часто встречаются в файловых системах, где видны папки и как они вложены.
Самому списку задают роль tree
, а его пунктам — treeitem
с нужным значением aria
.
Допустим, у нас есть основная (корневая) папка «Мои файлы» с двумя вложенными «Всякое» и «Разное». Внутри «Всякое» есть текстовые файлы и ещё одна папка «Черновики». Папки «Всякое» и «Разное» напрямую вложены в основную, так что они первого уровня aria
. Файлы и папки внутри первого уровня станут второго aria
. В папке второго уровня «Черновики» находятся файлы третьего уровня aria
.
<h3 id="label"> Мои файлы</h3><!-- Основная папка --><ul role="tree" aria-labelledby="label"> <!-- Вложенная папка № 1 --> <li role="treeitem" aria-level="1" aria-expanded="false" aria-selected="false" > <span> Всякое </span> <!-- Файлы папки № 1 --> <ul role="group"> <li role="treeitem" aria-level="2" aria-selected="false" > final-report.docx </li> <!-- Папка, вложенная в папку № 1 --> <li role="treeitem" aria-level="2" aria-selected="false" > <span> Черновики </span> </li> <!-- Файлы вложенной папки --> <ul role="group"> <li role="treeitem" aria-level="3" aria-selected="false" > final-report-draft.docx </li> </ul> </li> </ul> </li> <!-- Вложенная папка № 2 --> <li role="treeitem" aria-level="1" aria-expanded="false" aria-selected="false" > <span> Разное </span> <!-- Файлы папки № 2 --> <ul role="group"> <li role="treeitem" aria-level="2" aria-expanded="false" aria-selected="false" > <span> file-1.docx </span> </li> <!-- Другие элементы --> </ul> </li></ul>
<h3 id="label"> Мои файлы </h3> <!-- Основная папка --> <ul role="tree" aria-labelledby="label" > <!-- Вложенная папка № 1 --> <li role="treeitem" aria-level="1" aria-expanded="false" aria-selected="false" > <span> Всякое </span> <!-- Файлы папки № 1 --> <ul role="group"> <li role="treeitem" aria-level="2" aria-selected="false" > final-report.docx </li> <!-- Папка, вложенная в папку № 1 --> <li role="treeitem" aria-level="2" aria-selected="false" > <span> Черновики </span> </li> <!-- Файлы вложенной папки --> <ul role="group"> <li role="treeitem" aria-level="3" aria-selected="false" > final-report-draft.docx </li> </ul> </li> </ul> </li> <!-- Вложенная папка № 2 --> <li role="treeitem" aria-level="1" aria-expanded="false" aria-selected="false" > <span> Разное </span> <!-- Файлы папки № 2 --> <ul role="group"> <li role="treeitem" aria-level="2" aria-expanded="false" aria-selected="false" > <span> file-1.docx </span> </li> <!-- Другие элементы --> </ul> </li> </ul>
Древовидные сетки
СкопированоДревовидная сетка похожа на таблицу, которая состоит из нескольких раскрывающихся ячеек. Данные внутри ячеек расположены в определённой иерархии. Вы могли видеть такие сетки в почтовых клиентах. В них важно показать связь писем между собой.
Сетке задают роль treegrid
, а в строках row
уже группируют ячейки gridcell
.
В древовидных сетках aria
может быть только у строк с ролью row
. Предположим, мы хотим показать цепочку их трёх писем. У первого письма в ней будет первый уровень aria
, у ответа на него — второй aria
, а у ответа на ответ — третий aria
.
<h3 id="label"> Полученные письма</h3><table role="treegrid" aria-labelledby="label"> <colgroup> <col id="col-1"> <col id="col-2"> <col id="col-3"> </colgroup> <thead> <tr> <th scope="col"> Тема </th> <th scope="col"> Содержимое </th> <th scope="col"> Адрес </th> </tr> </thead> <tbody> <!-- Первое письмо --> <tr role="row" aria-level="1" aria-expanded="true" > <td role="gridcell"> Продам картофель </td> <td role="gridcell"> Дорого. Медленно. Некачественно. </td> <td role="gridcell"> <a href="mailto:potato@potatomail.mail"> potato@potatomail.mail </a> </td> </tr> <!-- Ответ на первое письмо --> <tr role="row" aria-level="2" > <td role="gridcell"> re: Продам картофель </td> <td role="gridcell"> У меня свой картошки полно. </td> <td role="gridcell"> <a href="mailto:potato2@potatomail.mail"> potato2@potatomail.mail </a> </td> </tr> <!-- Ответ на предыдущее письмо --> <tr role="row" aria-level="3" > <td role="gridcell"> re: Продам картофель </td> <td role="gridcell"> Если у тебя много картошки, отдай тогда мне. </td> <td role="gridcell"> <a href="mailto:potato3@potatomail.mail"> potato3@potatomail.mail </a> </td> </tr> </tbody></table>
<h3 id="label"> Полученные письма </h3> <table role="treegrid" aria-labelledby="label" > <colgroup> <col id="col-1"> <col id="col-2"> <col id="col-3"> </colgroup> <thead> <tr> <th scope="col"> Тема </th> <th scope="col"> Содержимое </th> <th scope="col"> Адрес </th> </tr> </thead> <tbody> <!-- Первое письмо --> <tr role="row" aria-level="1" aria-expanded="true" > <td role="gridcell"> Продам картофель </td> <td role="gridcell"> Дорого. Медленно. Некачественно. </td> <td role="gridcell"> <a href="mailto:potato@potatomail.mail"> potato@potatomail.mail </a> </td> </tr> <!-- Ответ на первое письмо --> <tr role="row" aria-level="2" > <td role="gridcell"> re: Продам картофель </td> <td role="gridcell"> У меня свой картошки полно. </td> <td role="gridcell"> <a href="mailto:potato2@potatomail.mail"> potato2@potatomail.mail </a> </td> </tr> <!-- Ответ на предыдущее письмо --> <tr role="row" aria-level="3" > <td role="gridcell"> re: Продам картофель </td> <td role="gridcell"> Если у тебя много картошки, отдай тогда мне. </td> <td role="gridcell"> <a href="mailto:potato3@potatomail.mail"> potato3@potatomail.mail </a> </td> </tr> </tbody> </table>
Комментарии
СкопированоНа многих социальных платформах можно отвечать на другие комментарии. Визуально это выглядит как вложенные в друг друга блоки с именем пользователя, временем публикации и текстом комментария. Один из способов передать это на уровне кода — aria
.
К примеру, первый пользователь отреагировал на пост в соцсети, другой оставил комментарий к нему, а третий — ответил на комментарий второго. Получается, первый комментарий с ролью comment
будет без aria
, второй — с aria
, а третий — с aria
.
<!-- Изначальный комментарий --><div role="comment"> <h3>А я — томат</h3> <time datetime="2024-01-03T14:04"> 3 дня назад </time> <p> Люблю окрошку на квасе 🥰 </p> <!-- Комментарий в ответ на первый --> <div role="comment" aria-level="1" > <h3>Сырная косичка</h3> <time datetime="2024-01-04T23:11"> 2 дня назад </time> <p> Окрошка на кефире лучшая! </p> <!-- Комментарий в ответ на второй --> <div role="comment" aria-level="2" > <h3>Картошка фри</h3> <time datetime="2024-01-05T10:34"> 1 день назад </time> <p> Фу, окрошка 🤢 А вот картошка… </p> </div> </div></div>
<!-- Изначальный комментарий --> <div role="comment" > <h3>А я — томат</h3> <time datetime="2024-01-03T14:04"> 3 дня назад </time> <p> Люблю окрошку на квасе 🥰 </p> <!-- Комментарий в ответ на первый --> <div role="comment" aria-level="1" > <h3>Сырная косичка</h3> <time datetime="2024-01-04T23:11"> 2 дня назад </time> <p> Окрошка на кефире лучшая! </p> <!-- Комментарий в ответ на второй --> <div role="comment" aria-level="2" > <h3>Картошка фри</h3> <time datetime="2024-01-05T10:34"> 1 день назад </time> <p> Фу, окрошка 🤢 А вот картошка… </p> </div> </div> </div>