Skip to content

Веб-доступність у 2026: скринридери, WCAG 2.2 і практики, що реально працюють

Доступність - це не чекліст, який запускають наприкінці спринту. Це набір структурних рішень - семантичний HTML, управління фокусом, ARIA-контракти - які або закладаються під час розробки, або коштують утричі дорожче при рефакторингу.

Веб-доступність: скринридер, клавіатурна навігація, діаграма WCAG 2.2 та ARIA roles
Опубліковано:Оновлено:Час читання:22 хв читання

Минулого року я три дні аудирував checkout-потік, який мав рейтинг 4.8/5 у дизайн-ревʼю Figma. Візуально - бездоганно. Але користувачі, що працюють лише з клавіатурою, не могли перейти в поле промокоду: там був <div> з обробником click, без tabindex, без role. Користувачі скринридерів чули 'без назви' на кожному інпуті, бо дизайнер використав placeholder як лейбл, а розробник скопіював паттерн. Повідомлення про помилки відображались червоним, але не були програмно повʼязані з полями. Кнопка 'Оформити замовлення' перехоплювала Enter, але не Space. Кожен із цих багів був невидимий для всіх, хто використовує мишу.

Це стійкий паттерн проблем із доступністю: вони невидимі для більшості команди і повністю блокують конкретну групу користувачів. У цьому пості я розбираю, як скринридери реально парсять DOM, що вимагає WCAG 2.2 у конкретних термінах реалізації, які паттерни клавіатурної навігації ламаються найчастіше і як побудувати тестовий процес, що знаходить ці проблеми раніше за користувачів.

Частина I - Хто використовує асистивні технології і чому це важливіше за compliance

  • Користувачі скринридерів: За даними ВООЗ, 285 мільйонів людей у світі мають порушення зору. Частки ринку скринридерів: JAWS (38%), NVDA (31%), VoiceOver (iOS/macOS, 18%), TalkBack (Android, 7%). NVDA - безкоштовний, VoiceOver вбудований у кожен пристрій Apple, TalkBack - в Android. Ці користувачі вже є у вашій аудиторії.
  • Користувачі лише з клавіатурою: Порушення моторики стосуються близько 2 мільйонів американців, що використовують альтернативні пристрої вводу - перемикачі, керування диханням, трекери погляду. Усі вони емулюють клавіатурний ввід на рівні ОС.
  • Когнітивні та навчальні порушення: Дислексія стосується 15–20% населення, СДУГ - 8–10% дорослих. Чітка типографічна ієрархія, передбачувані паттерни навігації та видимі стани фокусу допомагають усім цим групам.
  • Правовий ризик: ADA (США), EN 301 549 (ЄС) та Equality Act (Великобританія) встановлюють правові вимоги до цифрової доступності. Кількість ADA-позовів проти вебсайтів перевищила 4600 у 2023 році (UsableNet).
  • Тимчасові та ситуативні обмеження: Зламана рука, яскраве сонце, гучне середовище - контраст, клавіатурне керування та субтитри допомагають усім у субоптимальних умовах.

Частина II - Як скринридери реально парсять DOM

Ментальна модель, що прибирає більшість ARIA-помилок: скринридери читають не HTML - вони читають дерево доступності. Це паралельна структура, яку браузер будує з DOM та передає через платформенні API. Кожен вузол має чотири ключових властивості: role, name, state і value.

  • Role: Визначається тегом HTML-елемента або перевизначається атрибутом role. <div> без role - 'generic' контейнер: скринридер прочитає його текст у режимі перегляду, але користувачі не знайдуть його за швидкими клавішами.
  • Name: Доступне імʼя - те, що скринридер оголошує при фокусуванні. Джерела за пріоритетом: aria-labelledby, aria-label, вміст елемента, повʼязаний <label>. Placeholder - НЕ джерело імені.
  • State: Розгорнуто/згорнуто (aria-expanded), відмічено (aria-checked), невалідно (aria-invalid). Стан має оновлюватись програмно при зміні.
  • Режим перегляду vs інтерактивний режим: NVDA/JAWS за замовчуванням у режимі перегляду - стрілки переміщують віртуальний курсор по дереву доступності. При фокусуванні текстового інпуту переходять в інтерактивний режим. Нативна семантика критична - <div> з onclick не перемикає режим.

Частина III - Клавіатурна навігація: паттерни, що ламаються найчастіше

  • Порядок табуляції та порядок DOM: CSS flexbox і grid дозволяють візуально переставляти елементи без зміни порядку DOM - це розриває відповідність між візуальним та клавіатурним порядком. Порядок джерела DOM має відповідати передбаченому порядку читання.
  • Focus trap у модальних вікнах: При відкритті модала фокус має бути заблокований всередині. Табуляція циклічно переміщується лише по фокусованих елементах модала. При закритті фокус повертається до тригера. HTML <dialog> обробляє це нативно.
  • Клавіатурні паттерни для кастомних віджетів: ARIA APG визначає очікувану поведінку клавіатури. Кастомний дропдаун: Enter/Space відкриває меню, стрілки навігують по опціях, Enter вибирає, Escape закриває. Реалізація половини паттерну гірша за відсутність реалізації.
  • Skip navigation links: Перший фокусований елемент на кожній сторінці - посилання 'Перейти до основного вмісту'. <a href='#main-content' class='sr-only focus:not-sr-only'>Перейти до основного вмісту</a> плюс <main id='main-content' tabindex='-1'>.
  • Видимість фокусу: WCAG 2.2 SC 2.4.11 вимагає, щоб сфокусований елемент не був повністю прихований sticky-заголовками. Використовуйте scroll-margin-top та :focus-visible.

Частина IV - WCAG 2.2: критерії, що реально зустрічаються в аудитах

  • SC 1.1.1 Нетекстовий контент (Level A): Кожне зображення має мати текстову альтернативу. Інформаційні: alt описує вміст. Декоративні: alt=''. Функціональні іконки-кнопки: aria-label описує дію.
  • SC 1.4.3 Контрастність (Level AA): Звичайний текст - 4.5:1, великий - 3:1, UI-компоненти - 3:1.
  • SC 2.1.1 Клавіатура (Level A): Весь функціонал доступний з клавіатури. Кожен click на ненативному елементі потребує відповідного keydown для Enter і часто Space.
  • SC 3.3.1 та 3.3.2 (Level A): Помилки описані текстом, не тільки кольором. Повідомлення програмно повʼязане з інпутом через aria-describedby, інпут має aria-invalid='true'.
  • SC 4.1.2 Імʼя, роль, значення (Level A): Для всіх UI-компонентів імʼя, роль і стан мають визначатись асистивними технологіями.

Частина V - Типові production-помилки і паттерн виправлення

  • Кнопки з `<div>` і `<span>`: <div onClick={handler}> - немає role, немає доступу з клавіатури. Використовуйте <button type='button'> для всіх інтерактивних елементів.
  • Кнопки-іконки без доступного імені: Додайте aria-label='Закрити діалог' або прихований текст <span class='sr-only'>Закрити</span>. На SVG - aria-hidden='true'.
  • Поля форм без постійних лейблів: Завжди використовуйте <label for> або aria-label. Повідомлення про помилки: aria-describedby + aria-invalid='true'.
  • Інформація лише через колір: Доповнюйте колір текстовим лейблом, паттерном або іконкою з alt.
  • Динамічний вміст без оголошення: Додайте aria-live='polite' на контейнер із динамічними оновленнями. Контейнер має існувати в DOM до оновлення.
  • Нескінченне прокручування без виходу з клавіатури: Пагінація або кнопка 'Завантажити ще' в кінці батча.

Частина VI - Тестування

  • Автоматизація: axe-core в CI: @axe-core/playwright. Завершуйте збірку при critical або serious порушеннях.
  • Тестування клавіатурою: Tab по всіх інтерактивних елементах. Кожен має бути досяжним, видимим при фокусуванні та керованим через Enter/Space.
  • Тестування скринридером: На macOS: VoiceOver (Command+F5) з Safari. На Windows: NVDA (безкоштовний) з Firefox або Chrome.

Частина VII - Доступні паттерни компонентів

  • Модальні діалоги: role='dialog', aria-modal='true', aria-labelledby. Фокус переміщується в діалог при відкритті, блокується всередині, Escape закриває, фокус повертається до тригера. HTML <dialog> обробляє більшість цього нативно.
  • Валідація форм: aria-invalid='true' на інпуті, aria-describedby вказує на повідомлення про помилку. Підсумкові помилки: aria-live='assertive' зведення вгорі форми.
  • ARIA live regions для toast-сповіщень: <div role='status' aria-live='polite' aria-atomic='true'> оголошує зміни вмісту без переривання поточного читання.
  • Кастомні дропдауни vs нативний `<select>`: Нативний <select> повністю доступний всюди. Якщо будуєте кастомний - використовуйте паттерн combobox з APG та @radix-ui/react-select.
  • Таблиці даних: Нативні <table>, <th scope='col'>, <caption>. Уникайте CSS grid або divs для табличних даних.

Висновок

Борг із доступності в більшості production-застосунків виникає з одного джерела: інтерактивні компоненти на дженерик-елементах, лейбли що існують лише візуально, зміни стану невидимі для дерева доступності, і управління фокусом яке ніколи не розглядалось.

Практичний шлях: додайте axe-core в CI-пайплайн цього тижня. Додайте тестування клавіатурою до визначення готовності. Використовуйте нативні HTML-елементи там де використовуєте <div>. Використовуйте Radix UI або React Aria для складних віджетів.

Для аудиту доступності або доступної frontend-реалізації - послуга аудиту доступності | технічне SEO | обговорити проєкт.

Джерела

Схожі статті

Архітектура веб-продуктивності: системний аналіз 12 інженерних принципів (видання 2026)

Глибокий технічний розбір веб-продуктивності 2026 року: фізика мереж, конвеєри зображень, моделі виконання JavaScript, Critical Rendering Path, edge-обчислення, Core Web Vitals та продакшн RUM - з реальними бенчмарками та конкретними прикладами реалізації.

EngineeringArchitectureCore Web Vitals
Читати статтю

React 19: useOptimistic, use(), Server Actions - механізм і архітектура (2026)

Детальний розбір п'яти нових примітивів React 19: useOptimistic, use(), Server Actions, useActionState, useFormStatus. Action-based mutation архітектура, що замінює Redux/Zustand для серверних мутацій.

React 19ArchitectureNext.js
Читати статтю

Partial Prerendering (PPR) у продакшні: архітектурні патерни (2026)

Детальний розбір Next.js Partial Prerendering у продакшні. Механізм двофазної відповіді, правила розміщення Suspense-меж, взаємодія з Full Route Cache, дизайн fallback для нульового CLS, виміряні TTFB/LCP, порівняння з ISR+CSR та full SSR і фреймворк прийняття рішень.

Next.jsPerformancePPR
Читати статтю