ARIA-атрибуты

SVG-анимации, создаваемые через Vivus, относятся к классу визуально активного контента, который может нести как декоративную, так и смысловую нагрузку. Корректная разметка ARIA-атрибутами определяет поведение таких элементов в скринридерах и вспомогательных технологиях, а также влияет на восприятие динамического контента при навигации с клавиатуры и использовании альтернативных режимов отображения.

В контексте SVG ключевым является различие между декоративной графикой и информативной графикой. Vivus, как библиотека, анимирует путь (stroke-dashoffset) и визуально «рисует» элементы, что часто воспринимается как чистая анимация без семантики. В таких случаях ARIA управляет тем, должен ли этот контент вообще быть доступен для озвучивания.


Базовая семантика SVG в связке с ARIA

SVG по умолчанию не всегда корректно интерпретируется вспомогательными технологиями. Для явного определения роли используются атрибуты:

  • role="img" — обозначение SVG как изображения с семантическим значением
  • role="presentation" или role="none" — полное исключение из accessibility tree
  • aria-hidden="true" — скрытие от скринридеров без изменения визуального отображения

Типовой подход зависит от назначения анимации Vivus.

<svg id="logo" role="img" aria-label="Анимированный логотип компании"></svg>

В случае декоративного эффекта:

<svg id="decor" aria-hidden="true"></svg>

Использование aria-hidden критично для анимаций, не несущих смысловой нагрузки, поскольку Vivus может создавать значительный поток DOM-изменений через анимацию путей.


aria-label и aria-labelledby в SVG с Vivus

Когда SVG несёт смысловую нагрузку, текстовое описание должно быть отделено от визуального содержимого. Основные механизмы:

  • aria-label — краткое описание целиком на SVG-элементе
  • aria-labelledby — ссылка на текстовый элемент внутри документа
  • <title> и <desc> внутри SVG — нативные средства SVG-описания

Пример с aria-labelledby:

<svg id="chart" role="img" aria-labelledby="chartTitle chartDesc">
  <title id="chartTitle">График роста продаж</title>
  <desc id="chartDesc">Линейная диаграмма с ростом показателей за год</desc>
</svg>

Vivus в данном контексте не изменяет семантику, но анимация может задерживать появление элементов, поэтому важно учитывать момент, когда скринридер получает доступ к DOM.


Vivus и момент инициализации доступности

Vivus часто используется в режиме:

  • autostart
  • inViewport
  • manual

При autostart SVG начинает анимацию сразу после загрузки DOM, что создаёт риск озвучивания «недорисованного» контента. Скринридеры могут зафиксировать частично отрисованные элементы как полный объект.

При inViewport доступность зависит от появления элемента в области видимости, что требует синхронизации ARIA-состояний.

Практика управления состоянием:

const animation = new Vivus('logo', {
  type: 'delayed',
  duration: 120,
  start: 'inViewport'
}, () => {
  document.getElementById('logo').setAttribute('aria-busy', 'false');
});

document.getElementById('logo').setAttribute('aria-busy', 'true');

Атрибут aria-busy отражает состояние незавершённой визуальной отрисовки.


aria-live в контексте SVG-анимации

SVG с Vivus редко требует aria-live, однако в случаях, когда анимация отражает изменение данных (например, индикаторы прогресса), возможно использование:

  • aria-live="polite" — ненавязчивое обновление
  • aria-live="assertive" — приоритетное уведомление
<svg id="progress" aria-live="polite" role="img"></svg>

Использование требует осторожности, так как Vivus обновляет только визуальный слой, а не текстовое содержимое. Скринридер не получает новых текстовых узлов автоматически.


aria-hidden и контроль декоративных анимаций

Большая часть применений Vivus относится к декоративной анимации: логотипы, иллюстрации, микроинтеракции интерфейса. В таких случаях предпочтительно полное исключение из accessibility tree:

<svg id="line-art" aria-hidden="true"></svg>

Такой подход предотвращает:

  • дублирование информации скринридером
  • озвучивание неинформативных анимаций
  • перегрузку навигации

Особенно критично при множественных SVG-анимациях на одной странице.


Взаимодействие ARIA и CSS prefers-reduced-motion

ARIA не управляет визуальным отключением анимации, но используется совместно с системными предпочтениями:

@media (prefers-reduced-motion: reduce) {
  svg path {
    animation: none !important;
  }
}

Сторона JavaScript может отключать Vivus полностью:

if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
  document.getElementById('logo').setAttribute('aria-hidden', 'false');
}

В таких сценариях SVG часто переключается в статичное состояние, при этом ARIA остаётся единственным источником семантики.


aria-busy при управлении состоянием Vivus

Анимация рисования линий представляет собой процесс, который может интерпретироваться как загрузка или вычисление. Атрибут aria-busy отражает промежуточное состояние:

  • true — анимация выполняется
  • false — завершена
const svg = document.getElementById('logo');

svg.setAttribute('aria-busy', 'true');

new Vivus('logo', { duration: 80 }, () => {
  svg.setAttribute('aria-busy', 'false');
});

Это особенно актуально для сложных SVG с большим количеством путей, где визуальная отрисовка занимает заметное время.


Контейнерная доступность и focus management

SVG-элементы с Vivus часто помещаются внутри интерактивных контейнеров (button, a). В таких случаях ARIA не заменяет нативную семантику HTML.

Пример корректной структуры:

<button aria-label="Запустить анимацию логотипа">
  <svg id="logo"></svg>
</button>

При ручном запуске Vivus через событие клика необходимо учитывать синхронизацию состояния:

button.addEventListener('click', () => {
  svg.setAttribute('aria-pressed', 'true');

  vivus.reset().play();
});

Атрибут aria-pressed применяется, если SVG-элемент отражает переключаемое состояние.


SVG title/desc против ARIA-атрибутов

SVG поддерживает собственные механизмы описания:

  • <title>
  • <desc>

ARIA в этом случае играет вторичную роль, но может переопределять или дополнять семантику.

Приоритет интерпретации:

  1. aria-labelledby
  2. aria-label
  3. <title> внутри SVG
  4. роль элемента (role)

Vivus не влияет на этот порядок, но влияет на момент доступности элементов в DOM.


Типовые ошибки интеграции Vivus и ARIA

Наиболее распространённые проблемы:

  • отсутствие aria-hidden у декоративных анимаций
  • использование aria-label без текстовой альтернативы
  • анимация без учета aria-busy
  • динамическое изменение SVG без обновления ARIA-состояний
  • одновременное использование aria-label и <title> с конфликтующим смыслом

Особенно критичным является случай, когда Vivus используется для логотипов без семантического описания, что делает элемент невидимым для вспомогательных технологий.


Динамическое обновление ARIA при изменении SVG

При перезапуске или повторной анимации Vivus требуется синхронизация состояний:

function restartAnimation() {
  const svg = document.getElementById('logo');

  svg.setAttribute('aria-busy', 'true');

  vivus.reset().play();

  vivus.setCallback(() => {
    svg.setAttribute('aria-busy', 'false');
  });
}

В сложных интерфейсах подобная синхронизация предотвращает рассогласование между визуальной и семантической моделью документа.