Гид по технологиям

Доступная полоса прогресса в React

3 min read Accessibility Обновлено 20 Nov 2025
Доступная полоса прогресса в React
Доступная полоса прогресса в 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-элемент . Он уже семантически корректен и поддерживается экранными читалками:

50%

Преимущества нативного элемента:

  • встроенная семантика;
  • минимальные усилия по доступности;
  • меньше кастомных стилей, меньше рисков сломать 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 , либо role=”progressbar” задан верно.
  • Для определяемого прогресса заданы 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). В простых сценариях используйте , в сложных — кастомный компонент, соблюдая чеклист выше.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Запустить вентилятор HVAC через Nest
Умный дом

Запустить вентилятор HVAC через Nest

Автообои Bing для Ubuntu — с водяным знаком и без
Linux

Автообои Bing для Ubuntu — с водяным знаком и без

Google Assistant на Galaxy Watch 4
Гаджеты

Google Assistant на Galaxy Watch 4

AI‑поиск YouTube: как включить и использовать
Технологии

AI‑поиск YouTube: как включить и использовать

Нет устройства вывода аудио в Windows — исправление
Устранение неполадок

Нет устройства вывода аудио в Windows — исправление

Как установить и управлять шрифтами в Windows 10
Windows

Как установить и управлять шрифтами в Windows 10