Реализация поддержки VoiceOver/Screen Reader для сайта (WCAG)

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация поддержки VoiceOver/Screen Reader для сайта (WCAG)
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация поддержки VoiceOver/Screen Reader для сайта (WCAG)

Screen reader — программа экранного доступа для незрячих и слабовидящих пользователей. VoiceOver (macOS/iOS), NVDA и JAWS (Windows), TalkBack (Android) озвучивают содержимое страницы и дают возможность навигации с клавиатуры. WCAG 2.1 уровень AA обязывает обеспечить полную доступность для screen reader.

Как работает screen reader

Screen reader читает DOM-дерево и использует Accessibility Tree — специальное представление страницы, которое браузер строит из HTML и ARIA-атрибутов. Пользователь перемещается по заголовкам (H1-H6), ссылкам, формам, таблицам с помощью специальных клавиш.

Базовые требования

Семантическая разметка вместо div-soup:

<!-- Плохо -->
<div class="header">
  <div class="nav">
    <div class="nav-item" onclick="go('/home')">Главная</div>
  </div>
</div>

<!-- Хорошо -->
<header>
  <nav aria-label="Основная навигация">
    <ul>
      <li><a href="/home">Главная</a></li>
    </ul>
  </nav>
</header>

Ориентиры (landmarks) для навигации:

<header>...</header>
<nav aria-label="Основная навигация">...</nav>
<main>
  <article>...</article>
  <aside aria-label="Связанные материалы">...</aside>
</main>
<footer>...</footer>

Формы

<!-- Каждое поле формы должно иметь метку -->
<label for="email">Email</label>
<input type="email" id="email" name="email"
       aria-describedby="email-hint email-error"
       aria-required="true">
<span id="email-hint" class="hint">Мы не будем отправлять спам</span>
<span id="email-error" role="alert" aria-live="polite"></span>

<!-- Сгруппированные поля -->
<fieldset>
  <legend>Способ оплаты</legend>
  <label><input type="radio" name="payment" value="card"> Карта</label>
  <label><input type="radio" name="payment" value="cash"> Наличные</label>
</fieldset>

Динамический контент и SPA

Основная проблема SPA для screen reader — динамические обновления DOM не объявляются автоматически.

// React — объявление о загрузке данных
function DataSection({ isLoading, data }) {
    return (
        <section>
            {/* aria-live для объявления изменений */}
            <div aria-live="polite" aria-atomic="true" className="sr-only">
                {isLoading ? 'Загрузка данных...' : 'Данные загружены'}
            </div>

            {isLoading ? (
                <div aria-busy="true">
                    <span className="sr-only">Загрузка...</span>
                    <Spinner aria-hidden="true" />
                </div>
            ) : (
                <ul>
                    {data.map(item => <li key={item.id}>{item.title}</li>)}
                </ul>
            )}
        </section>
    );
}

Управление фокусом при навигации

// При переходе между страницами в SPA — перенос фокуса на заголовок страницы
import { useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';

function PageTitle({ title }) {
    const titleRef = useRef(null);
    const location = useLocation();

    useEffect(() => {
        titleRef.current?.focus();
        document.title = title;
    }, [location.pathname]);

    return (
        <h1 tabIndex={-1} ref={titleRef} className="focus-invisible">
            {title}
        </h1>
    );
}

Изображения и медиа

<!-- Информативное изображение -->
<img src="graph.png" alt="График роста продаж: +35% в Q3 2024">

<!-- Декоративное изображение -->
<img src="decorative-bg.png" alt="" role="presentation">

<!-- Сложная диаграмма — дополнительное текстовое описание -->
<figure>
    <img src="complex-chart.png" alt="Диаграмма распределения доходов"
         aria-describedby="chart-desc">
    <figcaption id="chart-desc">
        Диаграмма показывает: 40% доходов — продукт A, 35% — продукт B, 25% — прочее.
    </figcaption>
</figure>

Тестирование со screen reader

Инструменты:
- NVDA (Windows, бесплатно) — наиболее распространённый
- JAWS (Windows, коммерческий) — корпоративный стандарт
- VoiceOver (macOS: Cmd+F5, iOS: тройное нажатие Home)
- ChromeVox (Chrome extension)

Автоматическое тестирование:
- axe-core — библиотека для Playwright/Cypress
- jest-axe — для unit-тестов React компонентов
// Jest + jest-axe
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);

test('form is accessible', async () => {
    const { container } = render(<ContactForm />);
    const results = await axe(container);
    expect(results).toHaveNoViolations();
});

Срок реализации

  • Аудит текущего состояния: 1–2 дня
  • Исправление семантики и ARIA на существующем проекте: 3–7 дней
  • Тестирование со screen reader + доводка: 2–3 дня