Веб используют самые разные люди, в том числе с нарушениями зрения или моторики. Для таких групп доступны вспомогательные технологии, которые значительно упрощают работу с веб-приложениями. Кроме того, проектирование приложения с учётом доступности обычно улучшает пользовательский опыт для всех.
Подробное введение в вопросы и техники проектирования доступных приложений см. в курсе Google web.dev Learn Accessibility.
На этой странице описаны лучшие практики разработки Angular-приложений, которые хорошо работают для всех пользователей, включая тех, кто полагается на вспомогательные технологии.
Атрибуты доступности
Создание доступных веб-интерфейсов часто требует установки атрибутов Accessible Rich Internet Applications (ARIA), чтобы передать семантический смысл там, где он иначе мог бы отсутствовать. Используйте синтаксис привязки атрибутов в шаблоне для управления значениями атрибутов, связанных с доступностью.
ARIA-атрибуты и свойства
При привязке ARIA-атрибутов в Angular их можно использовать напрямую, как и любые другие HTML-атрибуты.
<button [aria-label]="myActionLabel">…</button>
Статические ARIA-атрибуты работают как обычные HTML-атрибуты.
<button aria-label="Save document">…</button>
ПОЛЕЗНО: По соглашению HTML-атрибуты используют имена в нижнем регистре (tabindex), а свойства — в camelCase (tabIndex).
Некоторые ARIA-паттерны предоставляют DOM API или входы директив, принимающие структурированные значения (например, коллекции ссылок на Element). В таких случаях используйте стандартную привязку свойств, чтобы базовые связи оставались синхронизированными.
@Component({
template: `
<h2 #dialogTitle>Attention</h2>
<p #dialogDescription>Please review your answers before continuing.</p>
<section role="dialog" [ariaLabelledByElements]="[dialogTitle, dialogDescription]">
<ng-content />
</section>
`,
})
export class ReviewDialog {}
Здесь [ariaLabelledByElements] принимает массив элементов, поэтому привязка свойства поддерживает актуальные ссылки на элементы при изменении данных шаблона.
Сводку синтаксиса ARIA-атрибутов см. в руководстве по привязкам.
UI-компоненты Angular
Библиотека Angular Material, поддерживаемая командой Angular, — это набор переиспользуемых UI-компонентов, ориентированных на полную доступность.
Component Development Kit (CDK) включает пакет a11y с инструментами для различных аспектов доступности.
Например:
LiveAnnouncerобъявляет сообщения для пользователей экранных читалок через регионaria-live. Подробнее о регионах aria-live см. в документации W3C.Директива
cdkTrapFocusудерживает фокус по клавише Tab внутри элемента. Используйте её для доступных компонентов вроде модальных окон, где фокус должен быть ограничен.
Полное описание этих и других инструментов см. в обзоре доступности Angular CDK.
Для кастомных компонентов, которым нужны переиспользуемые паттерны взаимодействия WAI-ARIA, Angular Aria предоставляет headless-директивы для паттернов вроде accordion, combobox, listbox, menu, tabs и toolbar. Эти директивы обрабатывают клавиатурное взаимодействие, ARIA-атрибуты, управление фокусом и поддержку экранных читалок, а вы задаёте HTML-структуру и стили приложения.
Расширение нативных элементов
Нативные HTML-элементы реализуют ряд стандартных паттернов взаимодействия, важных для доступности. При разработке Angular-компонентов по возможности переиспользуйте эти нативные элементы напрямую, а не воспроизводите уже хорошо поддерживаемое поведение.
Например, вместо создания кастомного элемента для нового вида кнопки создайте компонент с селектором-атрибутом на нативном элементе <button>.
Чаще всего это относится к <button> и <a>, но подходит и для многих других типов элементов.
Примеры этого паттерна в Angular Material:
MatButton, MatTabNav и MatTable.
Использование контейнеров для нативных элементов
Иногда для корректного нативного элемента нужен контейнер.
Например, нативный <input> не может иметь дочерних элементов, поэтому кастомные поля ввода оборачивают <input> дополнительными элементами.
Если просто включить <input> в шаблон кастомного компонента, пользователи компонента не смогут задать произвольные свойства и атрибуты для <input>.
Вместо этого создайте контейнерный компонент с проекцией контента, включающий нативный элемент в API компонента.
Пример этого паттерна — MatFormField.
Практический пример: кастомный индикатор прогресса
Следующий пример показывает, как сделать индикатор прогресса доступным с помощью host binding для управления атрибутами доступности.
- Компонент определяет элемент с поддержкой доступности: стандартный HTML-атрибут
roleи ARIA-атрибуты. ARIA-атрибутaria-valuenowпривязан к пользовательскому вводу. - В шаблоне атрибут
aria-labelобеспечивает доступность элемента для экранных читалок.
Маршрутизация
Управление фокусом после навигации
Отслеживание и управление фокусом в интерфейсе важно при проектировании с учётом доступности. При использовании маршрутизации Angular нужно решить, куда переходит фокус страницы после навигации.
Чтобы не полагаться только на визуальные подсказки, код маршрутизации должен обновлять фокус после перехода на страницу.
Используйте событие NavigationEnd из сервиса Router, чтобы знать, когда обновлять фокус.
В следующем примере показано, как найти и сфокусировать заголовок основного контента в DOM после навигации.
router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe(() => {
const mainHeader = document.querySelector('#main-content-header');
if (mainHeader) {
mainHeader.focus();
}
});
В реальном приложении элемент, получающий фокус, зависит от структуры и макета.
Сфокусированный элемент должен позволить пользователю сразу перейти к основному контенту, который только что отобразился после маршрутизации.
Следует избегать ситуаций, когда после смены маршрута фокус возвращается к элементу body.
Идентификация активных ссылок
CSS-классы, применяемые к активным элементам RouterLink, например RouterLinkActive, дают визуальную подсказку об активной ссылке.
К сожалению, визуальная подсказка не помогает слепым и слабовидящим пользователям.
Атрибут aria-current на элементе помогает идентифицировать активную ссылку.
Подробнее см. aria-current на MDN.
Директива RouterLinkActive предоставляет вход ariaCurrentWhenActive, который устанавливает aria-current в указанное значение, когда ссылка становится активной.
В следующем примере к активным ссылкам применяется класс active-page, а атрибут aria-current устанавливается в "page":
<nav>
<a routerLink="home" routerLinkActive="active-page" ariaCurrentWhenActive="page"> Home </a>
<a routerLink="about" routerLinkActive="active-page" ariaCurrentWhenActive="page"> About </a>
<a routerLink="shop" routerLinkActive="active-page" ariaCurrentWhenActive="page"> Shop </a>
</nav>
Отложенная загрузка
При использовании блоков @defer для ленивой загрузки контента учитывайте последствия для пользователей вспомогательных технологий.
Экранные читалки могут не объявлять автоматически об изменении контента при загрузке отложенных компонентов, и пользователь может не узнать о новом содержимом.
Чтобы изменения отложенного контента корректно объявлялись, оборачивайте блоки @defer в элементы с подходящими ARIA live-регионами.
Подробные рекомендации и примеры см. в разделе о доступности в руководстве по defer.
Дополнительные материалы
- Accessibility — Google Web Fundamentals
- Спецификация ARIA и практики авторинга
- Material Design — Accessibility
- Smashing Magazine
- Inclusive Components
- Ресурсы и примеры кода по доступности
- W3C — Web Accessibility Initiative
- Rob Dodson A11ycasts
- Angular ESLint предоставляет правила линтинга, помогающие соответствовать стандартам доступности.
Книги
- «A Web for Everyone: Designing Accessible User Experiences», Sarah Horton и Whitney Quesenbery
- «Inclusive Design Patterns», Heydon Pickering