Як зробити сайт доступним: покроковий план
Зробити сайт доступним означає забезпечити, щоб ним могли користуватися всі люди — включаючи тих, хто користується скрін-рідером, навігує лише клавіатурою, має порушення зору, слуху або когнітивні особливості. Це не потребує переробки сайту з нуля — більшість помилок виправляється за 1-2 спринти розробки.
Цей гід охоплює 10 кроків від базової семантики до тестування, з прикладами коду та конкретними критеріями WCAG 2.2.
Крок 1 — Семантичний HTML
Семантичний HTML — це фундамент доступності. Використовуйте HTML-теги за їхнім призначенням:
<!-- ❌ Погано -->
<div class="button" onclick="submit()">Надіслати</div>
<div class="heading">Заголовок розділу</div>
<!-- ✅ Добре -->
<button type="submit">Надіслати</button>
<h2>Заголовок розділу</h2>
Чому це важливо: Скрін-рідери використовують семантику для навігації. <button> автоматично отримує правильну роль, фокус і обробку клавіші Enter/Space. <div> — нічого з цього.
Ключові семантичні елементи:
<header>,<nav>,<main>,<footer>,<aside>,<section>,<article>— для landmark-навігації<h1>–<h6>— для заголовків (лише один<h1>на сторінці)<button>для дій,<a>для переходів<ul>,<ol>,<li>для списків
WCAG: 1.3.1 Info and Relationships (A), 4.1.2 Name, Role, Value (A)
Крок 2 — Alt-тексти для зображень
Кожне значуще зображення потребує альтернативного тексту (alt). Декоративні зображення мають порожній alt="".
<!-- ❌ Погано -->
<img src="chart.png" />
<img src="logo.png" alt="image" />
<!-- ✅ Добре -->
<img
src="chart.png"
alt="Діаграма: 73% державних сайтів не відповідають WCAG AA у 2026 році"
/>
<img src="logo.png" alt="ЦМЦІ — Центр моніторингу цифрової інклюзії" />
<img src="divider.png" alt="" />
<!-- декоративне зображення -->
Правила хорошого alt-тексту:
- Описуйте зміст і функцію, не зовнішній вигляд
- Для графіків — включайте ключовий висновок
- Для кнопок-іконок — описуйте дію ("Закрити меню", не "Іконка X")
- Максимум ~125 символів; для складних зображень — використовуйте
<figcaption>
WCAG: 1.1.1 Non-text Content (A)
Факт: 55% з 1 мільйона перевірених сайтів (WebAIM Million) мають хоча б одне зображення без alt-тексту.
Крок 3 — Контраст кольорів (мінімум 4.5:1)
Вимоги WCAG щодо контрасту:
| Тип тексту | Мінімум (AA) | Підвищений (AAA) |
|---|---|---|
| Звичайний текст (менше 18pt / 14pt bold) | 4.5:1 | 7:1 |
| Великий текст (18pt+ / 14pt+ bold) | 3:1 | 4.5:1 |
| Компоненти UI та графіка | 3:1 | — |
/* ❌ Погано: сірий #999 на білому #fff = 2.85:1 */
color: #999999;
background: #ffffff;
/* ✅ Добре: темно-сірий #595959 на білому = 7:1 */
color: #595959;
background: #ffffff;
Інструменти перевірки контрасту:
- WebAIM Contrast Checker
- Colour Contrast Analyser (десктопний застосунок)
- Вбудований інструмент у Chrome DevTools (Inspect → Accessibility)
WCAG: 1.4.3 Contrast (Minimum) (AA), 1.4.6 Contrast (Enhanced) (AAA)
Крок 4 — Навігація клавіатурою
Тест: закрийте мишу і спробуйте виконати типові дії лише клавіатурою:
- Tab — перехід між інтерактивними елементами
- Shift+Tab — назад
- Enter / Space — активація кнопок/посилань
- Стрілки — навігація всередині компонентів (меню, вкладки)
- Escape — закрити модальне вікно
Найпоширеніші проблеми клавіатурної навігації:
<!-- ❌ Пастка для клавіатури — не можна вийти -->
<div role="dialog">
<!-- фокус застряє тут, немає кнопки закриття, Escape не працює -->
</div>
<!-- ✅ Правильно — модальне вікно -->
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Підтвердження</h2>
<button>Підтвердити</button>
<button onclick="closeDialog()">Скасувати</button>
<!-- Escape також закриває через JS -->
</div>
Skip-link — перший елемент на сторінці, що дозволяє пропустити навігацію:
<a href="#main-content" class="skip-link">Перейти до основного контенту</a>
<!-- ... header, nav ... -->
<main id="main-content"></main>
.skip-link {
position: absolute;
top: -40px;
left: 0;
}
.skip-link:focus {
top: 0; /* з'являється при фокусі */
}
WCAG: 2.1.1 Keyboard (A), 2.1.2 No Keyboard Trap (A), 2.4.1 Bypass Blocks (A)
Крок 5 — Структура заголовків (H1–H6)
Заголовки — це навігаційна структура для скрін-рідерів. Правила:
- Один H1 на сторінці — назва сторінки
- Ієрархія не порушується — не стрибайте з H2 до H4
- Заголовки несуть зміст, а не є стилістичним інструментом
<!-- ❌ Погано -->
<h1>Назва сайту</h1>
<h3>Головний заголовок сторінки</h3>
<!-- пропущено h2 -->
<h2>Підзаголовок</h2>
<!-- ✅ Добре -->
<h1>Каталог товарів</h1>
<h2>Електроніка</h2>
<h3>Смартфони</h3>
<h3>Ноутбуки</h3>
<h2>Одяг</h2>
<h3>Чоловічий</h3>
Перевірте структуру заголовків розширенням HeadingsMap для Chrome/Firefox.
WCAG: 1.3.1 Info and Relationships (A), 2.4.6 Headings and Labels (AA)
Крок 6 — Доступні форми (labels)
Кожне поле форми повинно мати асоційований підпис:
<!-- ❌ Погано — placeholder не є label -->
<input type="email" placeholder="Email" />
<!-- ✅ Добре — явний label -->
<label for="email">Email</label>
<input type="email" id="email" name="email" />
<!-- ✅ Альтернатива — aria-label -->
<input type="search" aria-label="Пошук по сайту" placeholder="Введіть запит" />
Повідомлення про помилки:
<!-- ❌ Погано — лише колір -->
<input type="email" class="error" />
<!-- ✅ Добре — текстове повідомлення -->
<label for="email">Email</label>
<input
type="email"
id="email"
aria-describedby="email-error"
aria-invalid="true"
/>
<p id="email-error" role="alert">
Введіть коректну email-адресу (наприклад, [email protected])
</p>
WCAG: 1.3.1 Info and Relationships (A), 3.3.1 Error Identification (A), 3.3.2 Labels or Instructions (A)
Крок 7 — ARIA атрибути
Перше правило ARIA: не використовуйте ARIA, якщо нативний HTML справляється.
ARIA потрібний для:
- Кастомних компонентів (dropdown, tabs, accordion)
- Динамічного контенту (повідомлення, оновлення)
- Зв'язку між елементами
<!-- Кнопка з підказкою -->
<button aria-label="Видалити товар Чоловіча куртка">
<svg aria-hidden="true">...</svg>
</button>
<!-- Accordion -->
<button aria-expanded="false" aria-controls="section1">Розділ 1</button>
<div id="section1" hidden>Вміст розділу</div>
<!-- Live region для оновлень -->
<div aria-live="polite" aria-atomic="true">
<!-- Динамічно оновлюваний контент -->
</div>
Детальний гайд: ARIA атрибути для розробників
WCAG: 4.1.2 Name, Role, Value (A)
Крок 8 — Адаптивність (zoom 200%)
Сайт має коректно відображатись при збільшенні до 200% без горизонтального скролу і без втрати контенту.
/* ❌ Погано — фіксована ширина блокує zoom */
.container {
width: 960px;
overflow: hidden;
}
/* ✅ Добре — адаптивна ширина */
.container {
max-width: 1200px;
width: 100%;
}
/* Не заблоковуйте zoom в мета-тегу */
/* ❌ */ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
/* ✅ */ <meta name="viewport" content="width=device-width, initial-scale=1">
WCAG: 1.4.4 Resize Text (AA), 1.4.10 Reflow (AA)
Крок 9 — Анімації (prefers-reduced-motion)
Анімації можуть викликати запаморочення або епілептичні напади. Поважайте налаштування користувача:
/* Базові анімації */
.card {
transition: transform 0.3s ease;
}
/* Вимкнути для користувачів з відповідним налаштуванням */
@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
}
/* Або мінімальна анімація */
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Перевірте: Налаштування → Доступність → "Зменшити рух" (macOS), або Windows → Параметри → Спрощення доступу → "Показувати анімацію".
WCAG: 2.3.3 Animation from Interactions (AAA, але критично важливо)
Крок 10 — Тестування
Автоматизоване (виявляє ~40% помилок):
- ЦМЦІ /scan — безкоштовний WCAG аудит
- axe DevTools — Chrome/Firefox розширення
- Lighthouse (вбудований у Chrome DevTools)
Ручне тестування:
- Навігація лише Tab/Enter/Escape
- Збільшення до 200% у браузері
- Вимкнення CSS (перевірити логічний порядок)
- Перевірка без кольору (grayscale у налаштуваннях)
Скрін-рідер:
- NVDA (Windows, безкоштовний) — детальна інструкція
- VoiceOver (Mac/iOS, вбудований)
Чеклист перед запуском:
- Всі зображення мають alt-тексти або
alt="" - Контраст всіх текстів ≥ 4.5:1
- Навігація клавіатурою через весь сайт без пасток
- Видимий фокус-стан на всіх елементах
- Всі поля форм мають
<label> - Структура заголовків логічна (один H1, без пропусків)
-
<html lang="uk">встановлено - Skip-link на початку сторінки
- Zoom 200% без горизонтального скролу
- Скрін-рідер може прочитати весь контент