Доступная полоса прогресса в React
Кратко: реализуйте доступный прогресс-бар в React, задав семантику (role, aria-значения) и видимую подпись; учитывайте индикацию без определённого значения, поддержку prefers-reduced-motion и альтернативу через нативный элемент

Прогресс-бары повышают вовлечённость: они превращают ожидание в цель. Но видимые индикаторы должны быть понятны всем, включая пользователей экранных читалок. В этой статье — как правильно и доступно реализовать полосy прогресса в React, когда использовать нативный элемент, а когда — кастомный div, и какие атрибуты ARIA нужны.
Зачем это важно
Коротко: люди с нарушением зрения, а также пользователи клавиатуры и голосовых помощников должны понимать, сколько осталось до завершения операции. Семантика и текстовая подпись — ключевые элементы доступности.
Базовый компонент ProgressBar — пример
Ниже пример простого, но улучшенного и доступного компонента. Он корректно обрабатывает значения от 0 до 100, даёт подпись и использует aria-valuetext для ясности.
import React from 'react';
import PropTypes from 'prop-types';
const ProgressBar = ({ progress, labelId }) => {
const safeProgress = Math.max(0, Math.min(100, progress));
const container = {
height: 20,
width: '100%',
backgroundColor: '#ffffff',
borderRadius: 50,
margin: '1rem 0',
overflow: 'hidden'
};
const bar = {
height: '100%',
width: `${safeProgress}%`,
backgroundColor: '#90CAF9',
borderRadius: 'inherit',
transition: 'width 300ms ease'
};
const label = {
padding: '0 0.5rem',
color: '#000000',
fontSize: 12,
lineHeight: '20px'
};
return (
{`${safeProgress}%`}
);
};
ProgressBar.propTypes = {
progress: PropTypes.number.isRequired,
labelId: PropTypes.string
};
ProgressBar.defaultProps = {
labelId: 'progress-label'
};
export default ProgressBar;Пример использования:
Этот компонент:
- гарантирует, что значение всегда в диапазоне 0–100;
- предоставляет видимую подпись с id, на которую ссылается aria-labelledby;
- использует aria-valuetext для удобочитаемого текста в озвучивании;
- включает плавный CSS-переход, который можно отключить для пользователей, предпочитающих уменьшение анимаций.
Альтернатива: нативный элемент
Для простых случаев используйте HTML-элемент
Преимущества нативного элемента:
- встроенная семантика;
- минимальные усилия по доступности;
- меньше кастомных стилей, меньше рисков сломать aria-логику.
Ограничение: нативный
Индикация без определённого значения (indeterminate)
Когда точный прогресс неизвестен, не используйте aria-valuenow. Вместо этого дайте понятный текст и aria-label/aria-valuetext:
{/* анимация полосы без числового указания */}
Важно: экранные читалки ожидают либо конкретного значения, либо понятной текстовой индикации процесса.
Поддержка prefers-reduced-motion
Некоторым пользователям нежелательно анимированное движение. Добавьте CSS-поддержку prefers-reduced-motion и отключайте переходы:
@media (prefers-reduced-motion: reduce) {
.progress-bar-inner {
transition: none !important;
}
}Контраст и текст внутри полосы
Текст внутри полосы (например, “50%”) должен быть читаем при любом заполнении. Если цвет фона полосы и цвет текста дают низкий контраст, вынесите текст наружу или меняйте цвет текста в зависимости от заполнения.
Контрольные пункты (чеклист) для приёмки
- aria-role: либо nativ
- Для определяемого прогресса заданы aria-valuenow, aria-valuemin, aria-valuemax.
- Есть текстовая подпись: aria-labelledby или aria-label.
- Для indeterminate состояния aria-valuenow отсутствует; задан aria-valuetext или aria-label.
- Поддержка prefers-reduced-motion.
- Контраст текста и фона соответствует рекомендациям WCAG.
- Значение корректно ограничено (0–100) и не ломает вёрстку при крайних значениях.
Когда этот подход не сработает
- Если UX требует сложной кастомной графики (например, круговой прогресс со множеством слоёв), простого div+aria может быть недостаточно — нужно предоставить SVG с доступной подписью.
- В хорошо защищённых окружениях (старые версии браузеров или особые экранные читалки) поведение может немного отличаться — тестируйте на реальных устройствах.
Лучшие практики и рекомендации
- Предпочитайте нативный
- Всегда добавляйте видимую подпись и ссылку на неё через aria-labelledby.
- Для indeterminate состояния используйте aria-valuetext, не поддавайтесь искушению ставить бессмысленное aria-valuenow.
- Тестируйте с NVDA, VoiceOver и с клавиатурой.
Важно: поддержка семантики и текстовой подписи делает интерфейс полезным не только для людей с нарушениями, но и для всех пользователей.
Краткое резюме
Доступная полоса прогресса в React — это сочетание правильной семантики (role и aria-*), видимого текста и учёта особых случаев (indeterminate, reduced motion). В простых сценариях используйте
Похожие материалы
Запустить вентилятор HVAC через Nest
Автообои Bing для Ubuntu — с водяным знаком и без
Google Assistant на Galaxy Watch 4
AI‑поиск YouTube: как включить и использовать
Нет устройства вывода аудио в Windows — исправление