10 найпоширеніших помилок доступності та як їх виправити
96,3% вебсайтів мають хоча б одну помилку доступності рівня WCAG AA — це дані щорічного дослідження WebAIM Million, де перевіряється 1 мільйон сайтів. Середній сайт має 56 окремих порушень. Хороша новина: топ-10 помилок покривають понад 96% всіх виявлених проблем, і більшість із них виправляється за кілька годин.
Для кожної помилки: опис → приклад ❌ → виправлення ✅ → WCAG критерій.
1. Зображення без alt-текстів
Проблема: Скрін-рідер не може передати зміст зображення, якщо відсутній alt атрибут або він порожній для значущого зображення.
Частота: 55% сайтів (WebAIM Million 2025)
<!-- ❌ Погано -->
<img src="quarterly-report-chart.png" />
<img src="icon-warning.svg" alt="" />
<!-- ✅ Добре -->
<img
src="quarterly-report-chart.png"
alt="Квартальний звіт Q1 2026: доступність держсайтів зросла з 12% до 18%"
/>
<img src="icon-warning.svg" alt="Попередження" />
<img src="decorative-border.png" alt="" />
<!-- порожній alt для декоративних зображень -->
Правило: Декоративні зображення → alt="". Значущі → короткий опис змісту та функції. Кнопки-іконки → опис дії.
WCAG: 1.1.1 Non-text Content (рівень A)
2. Недостатній контраст тексту
Проблема: Текст не відрізняється від фону, що утруднює читання для людей з порушеннями зору, при яскравому освітленні або на старих моніторах.
Частота: 81% сайтів — найпоширеніша помилка!
/* ❌ Погано — сірий текст на білому фоні = 2.85:1 */
.subtitle {
color: #999999;
background: #ffffff;
}
/* ❌ Погано — синій на голубому = 1.8:1 */
.link {
color: #4488ff;
background: #ddeeff;
}
/* ✅ Добре — темний сірий на білому = 7:1 */
.subtitle {
color: #595959;
background: #ffffff;
}
/* ✅ Добре — синій на білому = 4.54:1 */
.link {
color: #1a5ea8;
background: #ffffff;
}
Вимоги:
- Звичайний текст: мінімум 4.5:1
- Великий текст (18pt / 14pt bold): мінімум 3:1
- Елементи UI (рамки форм, іконки): мінімум 3:1
Перевірте: WebAIM Contrast Checker
WCAG: 1.4.3 Contrast Minimum (рівень AA)
3. Контент поза landmark-областями
Проблема: Без семантичних landmark-елементів скрін-рідери не можуть швидко перейти до потрібної секції сторінки.
Частота: 43% сайтів
<!-- ❌ Погано — весь контент у div без ролей -->
<div class="header">...</div>
<div class="nav">...</div>
<div class="content">...</div>
<div class="footer">...</div>
<!-- ✅ Добре — семантична структура -->
<header>
<nav aria-label="Головна навігація">...</nav>
</header>
<main>
<h1>Заголовок сторінки</h1>
...
</main>
<aside aria-label="Пов'язані матеріали">...</aside>
<footer>...</footer>
Обов'язкові landmarks:
<header>абоrole="banner"— один на сторінку<nav>абоrole="navigation"— для кожного блоку навігації<main>абоrole="main"— основний контент, один на сторінку<footer>абоrole="contentinfo"— один на сторінку
WCAG: 1.3.1 Info and Relationships (рівень A), 2.4.1 Bypass Blocks (рівень A)
4. Посилання без зрозумілого тексту
Проблема: Посилання типу "Читати далі", "Клікніть тут", "Детальніше" — бессмисленні без контексту. Коли скрін-рідер перелічує всі посилання на сторінці, кожне має бути зрозумілим.
Частота: 50% сайтів
<!-- ❌ Погано -->
<a href="/articles/wcag">Читати далі</a>
<a href="/scan">Тут</a>
<!-- ✅ Добре — контекст у тексті -->
<a href="/articles/wcag">Читати далі про WCAG 2.2</a>
<a href="/scan">Перевірте свій сайт безкоштовно</a>
<!-- ✅ Альтернатива — aria-label для короткого тексту -->
<a href="/articles/wcag" aria-label="Читати статтю про WCAG 2.2">Читати далі</a>
<!-- ✅ Для іконок без тексту -->
<a href="https://twitter.com/cmci" aria-label="ЦМЦІ на Twitter">
<svg aria-hidden="true">...</svg>
</a>
WCAG: 2.4.4 Link Purpose (In Context) (рівень A), 2.4.9 Link Purpose (Link Only) (рівень AAA)
5. Порушена ієрархія заголовків
Проблема: Стрибки у рівнях заголовків (H1→H3, пропуск H2) порушують логічну структуру документа. Скрін-рідер не може орієнтуватись.
Частота: 42% сайтів
<!-- ❌ Погано — пропуск рівня -->
<h1>Назва сайту</h1>
<h3>Перший розділ</h3>
<!-- має бути h2 -->
<h5>Підрозділ</h5>
<!-- має бути h3 -->
<!-- ❌ Погано — декілька H1 -->
<h1>Головна сторінка</h1>
<h1>Новини</h1>
<h1>Про нас</h1>
<!-- ✅ Добре -->
<h1>Каталог послуг ЦМЦІ</h1>
<h2>Аудит доступності</h2>
<h3>Автоматичний аудит</h3>
<h3>Ручний аудит</h3>
<h2>Рейтинги</h2>
<h3>Держсайти</h3>
<h3>Банки</h3>
Перевірка: розширення HeadingsMap для Chrome або Firefox показує ієрархію заголовків у вигляді дерева.
WCAG: 1.3.1 Info and Relationships (рівень A)
6. Форми без label
Проблема: Поля форм без підписів незрозумілі для скрін-рідерів. Placeholder зникає при введенні і не є заміною для label.
Частота: 48% сайтів
<!-- ❌ Погано — немає label -->
<input type="text" placeholder="Ім'я" />
<input type="email" placeholder="Email" />
<!-- ❌ Погано — label є, але не асоційований -->
<label>Email</label>
<input type="email" />
<!-- ✅ Добре — явний label через for/id -->
<label for="user-name">Ім'я та прізвище</label>
<input type="text" id="user-name" name="name" autocomplete="name" />
<label for="user-email">Електронна пошта</label>
<input type="email" id="user-email" name="email" autocomplete="email" />
<!-- ✅ Альтернатива для компактних форм — aria-label -->
<input
type="search"
aria-label="Пошук по сайту"
placeholder="Введіть запит..."
/>
Бонус — autocomplete: додайте атрибут autocomplete до форм — це допомагає людям з когнітивними порушеннями та моторними обмеженнями.
WCAG: 1.3.1 Info and Relationships (A), 3.3.2 Labels or Instructions (A), 1.3.5 Identify Input Purpose (AA)
7. Відсутність skip-link
Проблема: Користувач клавіатури змушений натиснути Tab десятки разів через меню навігації, щоб дістатися до основного контенту — на кожній сторінці.
Частота: 87% сайтів (ВЕЛИЧЕЗНА прогалина!)
<!-- ✅ Додайте першим елементом у <body> -->
<a href="#main-content" class="skip-link"> Перейти до основного контенту </a>
<header>
<nav>...</nav>
</header>
<main id="main-content">
<h1>...</h1>
</main>
.skip-link {
position: absolute;
top: -40px;
left: 6px;
background: #000;
color: #fff;
padding: 8px;
z-index: 100;
text-decoration: none;
border-radius: 0 0 4px 4px;
}
.skip-link:focus {
top: 0; /* видний при фокусі клавіатури */
}
WCAG: 2.4.1 Bypass Blocks (рівень A)
8. Автоматичне відтворення відео/аудіо
Проблема: Автоматичне відтворення звуку заважає роботі скрін-рідерів (голос читача перекривається звуком сайту) і дратує всіх інших користувачів.
<!-- ❌ Погано -->
<video src="promo.mp4" autoplay></video>
<audio src="background.mp3" autoplay loop></audio>
<!-- ✅ Добре — без autoplay, з контролами -->
<video src="promo.mp4" controls>
<track
kind="captions"
src="captions-uk.vtt"
srclang="uk"
label="Українська"
/>
</video>
<!-- ✅ Якщо autoplay критично (Hero-відео з вимкненим звуком) -->
<video
src="hero.mp4"
autoplay
muted
loop
playsinline
aria-label="Демонстрація роботи аудиту доступності"
>
<!-- aria-label пояснює вміст відео -->
</video>
Правила:
- Якщо відео запускається автоматично — воно має бути беззвучним (muted)
- Завжди надавайте контроль для зупинки/паузи
- Відео з мовленням потребують субтитрів (не автогенерованих YouTube без перевірки)
WCAG: 1.4.2 Audio Control (A), 1.2.2 Captions (Prerecorded) (A)
9. Відсутність фокус-стану
Проблема: Стандартний контур фокусу часто прибирають з естетичних міркувань. Без нього користувачі клавіатури не бачать, де знаходиться фокус.
Частота: 69% сайтів прибирають або погано стилізують фокус
/* ❌ Смертний гріх доступності */
* {
outline: none;
}
:focus {
outline: 0;
}
a:focus {
outline: none;
}
/* ✅ Правильно — кастомний видимий фокус */
:focus-visible {
outline: 3px solid #0070f3;
outline-offset: 2px;
border-radius: 2px;
}
/* Для кнопок */
button:focus-visible {
outline: 3px solid #0070f3;
outline-offset: 3px;
box-shadow: 0 0 0 6px rgba(0, 112, 243, 0.2);
}
Примітка: Використовуйте :focus-visible замість :focus — він показує фокус лише при навігації клавіатурою, а не при кліку мишею (кращий UX для обох груп).
WCAG: 2.4.7 Focus Visible (AA), 2.4.11 Focus Not Obscured (AA — новий у WCAG 2.2)
10. Некоректний lang атрибут
Проблема: Без атрибута lang скрін-рідер не знає, якою мовою читати контент, і використовує налаштування системи за замовчуванням. Українець побачить текст, що читається польськими або англійськими правилами вимови.
Частота: 17% сайтів
<!-- ❌ Погано — немає lang -->
<html>
<head>
...
</head>
</html>
<!-- ❌ Погано — неправильний lang -->
<html lang="en">
<!-- сайт українською, але вказана англійська -->
<!-- ✅ Добре — українська мова -->
<html lang="uk">
<!-- ✅ Для мультимовних сторінок — lang на окремих елементах -->
<html lang="uk">
<p>Доступність важлива!</p>
<p lang="en">Accessibility matters!</p>
</html>
</html>
</html>
Додатково: якщо сторінка перемикається між мовами (наприклад, EN/UA), оновлюйте lang атрибут <html> при зміні мови.
WCAG: 3.1.1 Language of Page (A), 3.1.2 Language of Parts (AA)
Підсумкова таблиця
| # | Помилка | Частота | WCAG рівень | Час виправлення |
|---|---|---|---|---|
| 1 | Зображення без alt | 55% | A | 1-2 год |
| 2 | Поганий контраст | 81% | AA | 2-4 год |
| 3 | Немає landmarks | 43% | A | 2-4 год |
| 4 | Незрозумілі посилання | 50% | A | 1-2 год |
| 5 | Порушена ієрархія заголовків | 42% | A | 1-2 год |
| 6 | Форми без label | 48% | A | 2-4 год |
| 7 | Відсутній skip-link | 87% | A | 30 хв |
| 8 | Автовідтворення | Рідко | A | 30 хв |
| 9 | Прибраний фокус | 69% | AA | 1-2 год |
| 10 | Відсутній lang | 17% | A | 5 хв |