ARIA атрибуты для floating элементов

Floating элементы — это интерактивные элементы интерфейса, которые визуально “всплывают” над основным содержимым страницы: всплывающие подсказки (tooltips), контекстные меню, модальные окна, dropdown-меню и popovers. Для обеспечения доступности таких элементов крайне важно корректно использовать ARIA атрибуты, чтобы технологии вспомогательного доступа могли правильно интерпретировать состояние и поведение элемента.


Роль role в floating элементах

role задаёт семантическую роль элемента в документе, что позволяет скринридерам и другим вспомогательным технологиям правильно распознавать его назначение.

  • tooltip — используется для подсказок, которые появляются при наведении или фокусе на элементе. Пример:

    <button id="btn">Кнопка</button>
    <div role="tooltip" id="tooltip">Подсказка</div>

    Для связи кнопки и подсказки используется атрибут aria-describedby.

  • menu и menuitem — применяются для dropdown и контекстных меню.

    <ul role="menu" id="menu">
      <li role="menuitem">Пункт 1</li>
      <li role="menuitem">Пункт 2</li>
    </ul>
  • dialog — для модальных окон, popovers с интерактивным контентом.


Атрибуты aria для управления состоянием

ARIA предоставляет атрибуты, которые сообщают вспомогательным технологиям о текущем состоянии элемента:

  • aria-expanded — указывает, открыт ли всплывающий элемент.

    <button aria-expanded="false" aria-controls="dropdown">Меню</button>
    <ul id="dropdown" role="menu" hidden>
      <li role="menuitem">Пункт 1</li>
    </ul>

    При открытии меню aria-expanded меняется на "true".

  • aria-hidden — скрывает элементы от скринридеров. Часто используется для floating элементов, которые визуально скрыты:

    <div role="tooltip" aria-hidden="true">Подсказка</div>
  • aria-describedby — связывает управляющий элемент с описанием или подсказкой:

    <button aria-describedby="tooltip">Кнопка</button>
    <div role="tooltip" id="tooltip">Описание кнопки</div>
  • aria-labelledby — связывает элемент с заголовком, обычно для диалогов:

    <div role="dialog" aria-labelledby="dialogTitle">
      <h2 id="dialogTitle">Заголовок окна</h2>
    </div>
  • aria-activedescendant — указывает на активный элемент внутри контейнера, полезно для клавиатурной навигации в меню или списках.


Связь управляющего элемента и floating элемента

Floating элементы редко существуют сами по себе — они привязаны к управляющему элементу (кнопка, поле ввода). Ключевые ARIA атрибуты для этой связи:

  1. aria-controls — указывает на элемент, которым управляет управляющий элемент.

    <button aria-controls="menu" aria-expanded="false">Открыть меню</button>
    <ul id="menu" role="menu" hidden>...</ul>
  2. aria-describedby — для подсказок и пояснений, показываемых рядом с элементом.

  3. aria-labelledby — если floating элемент имеет собственный заголовок, полезно связать его с контейнером.


Управление доступностью с помощью Floating UI

Библиотека Floating UI предоставляет инструменты для точного позиционирования floating элементов, но для доступности необходимо управлять атрибутами ARIA вручную или через встроенные утилиты.

Пример tooltip с Floating UI и ARIA:

import {computePosition, offset, flip} from '@floating-ui/dom';

const button = document.querySelector('#btn');
const tooltip = document.querySelector('#tooltip');

button.addEventListener('mouseenter', () => {
  tooltip.setAttribute('aria-hidden', 'false');
  computePosition(button, tooltip, {
    middleware: [offset(5), flip()]
  }).then(({x, y}) => {
    Object.assign(tooltip.style, {
      left: `${x}px`,
      top: `${y}px`
    });
  });
});

button.addEventListener('mouseleave', () => {
  tooltip.setAttribute('aria-hidden', 'true');
});

В этом примере:

  • aria-hidden управляет видимостью подсказки для скринридеров.
  • computePosition отвечает за точное позиционирование над кнопкой.
  • Любые события открытия и закрытия должны синхронизироваться с aria-expanded или aria-hidden.

Практические рекомендации

  • Всегда задавать семантический role, соответствующий типу floating элемента.
  • Использовать aria-expanded для элементов, которые открываются/закрываются.
  • Связывать управляющий элемент и floating элемент через aria-controls и aria-describedby.
  • Для модальных окон использовать role="dialog" с aria-labelledby и опционально aria-describedby для пояснений.
  • При динамическом создании элементов не забывать обновлять ARIA-атрибуты и удалять их при закрытии.

Сценарии с клавиатурной навигацией

Для меню и списков важно использовать:

  • aria-activedescendant для указания текущего выбранного элемента.
  • Навигацию стрелками с обновлением aria-selected на активном элементе.
  • Фокус на управляющий элемент при закрытии floating элемента, чтобы не потерять контекст.

Правильная интеграция ARIA с floating элементами делает интерфейс доступным для всех пользователей, обеспечивая предсказуемое и корректное поведение для технологий вспомогательного доступа.