Сделать сайт доступным: Accessibility в PHP для всех пользователей

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему Accessibility — это не про «галочку», а про реальных людей

Представьте: вы заходите на сайт, а кнопка «Купить» не нажимается. Или текст сливается с фоном, как хамелеон на асфальте. Для человека с плохим зрением или моторными нарушениями это не «баг», а ежедневная реальность. Accessibility (a11y) — это не модный тренд, а мост, который соединяет ваш код с миллионами пользователей.

В России, по данным ВОЗ, более 12 миллионов человек имеют инвалидность. А если добавить пожилых людей, временные ограничения (сломанная рука, яркое солнце) — аудитория, которая нуждается в доступности, становится колоссальной. PHP разработка с учётом Accessibility — это не только этично, но и выгодно: поисковики любят семантику, а пользователи — удобство.

В этой статье мы разберём, как внедрить принципы WCAG (Web Content Accessibility Guidelines) прямо в PHP-код. Без воды, с живыми примерами и готовыми решениями.

С чего начать: семантическая разметка и PHP

Многие думают, что Accessibility — это только про CSS и JavaScript. Но корень проблемы часто лежит в серверной части. PHP генерирует HTML, и если этот HTML «глухой» — никакой фронтенд не спасёт.

Правильные заголовки и структура

Скринридеры (программы чтения с экрана) ориентируются на заголовки. Если у вас на странице один <h1>, а потом сразу <h3> — это как книга, где после оглавления идёт сноска. Нарушается иерархия.

Плохой подход:

<?php
// Генерация контента без учёта семантики
echo '<div class="title">' . $title . '</div>';
echo '<div class="subtitle">' . $subtitle . '</div>';
?>

Хороший подход (Accessibility в PHP):

<?php
// Семантическая структура для скринридеров
echo '<h1>' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</h1>';
echo '<h2>' . htmlspecialchars($subtitle, ENT_QUOTES, 'UTF-8') . '</h2>';
?>

Обратите внимание на htmlspecialchars() — это база безопасности и доступности. Спецсимволы в заголовках могут сломать разметку или быть неправильно прочитаны.

ARIA-атрибуты: когда HTML не хватает

ARIA (Accessible Rich Internet Applications) — это набор атрибутов, которые дополняют семантику. Например, если вы делаете кастомный выпадающий список на PHP и JavaScript, скринридеру нужно сказать: «Эй, это кнопка, которая открывает меню».

Пример генерации ARIA-совместимой кнопки:

<?php
function renderAccessibleButton(string $label, string $id): string {
    return sprintf(
        '<button id="%s" aria-expanded="false" aria-controls="menu-%s">%s</button>',
        htmlspecialchars($id),
        htmlspecialchars($id),
        htmlspecialchars($label)
    );
}
echo renderAccessibleButton('Меню', 'main-menu');
?>

Атрибут aria-expanded сообщает скринридеру, открыто ли меню. aria-controls связывает кнопку с выпадающим блоком. Это как GPS-навигатор для незрячего пользователя.

Работа с формами: ловушка для Accessibility

Формы — самое больное место. Пользователь заполняет поле, а скринридер говорит: «Редактирование текста». Какого текста? Для чего? Без меток — это казино.

Связываем label и input

В PHP вы часто генерируете поля динамически. Главное правило: каждый <input> должен иметь <label> с атрибутом for, или сам input должен быть обёрнут в label.

Пример для динамической формы:

<?php
$fields = [
    'name' => 'Имя',
    'email' => 'Email',
    'phone' => 'Телефон'
];
foreach ($fields as $key => $label):
?>
    <div class="form-group">
        <label for="input-<?= $key ?>"><?= htmlspecialchars($label) ?></label>
        <input type="text" id="input-<?= $key ?>" name="<?= $key ?>" required>
    </div>
<?php endforeach; ?>

Обратите внимание: id и for должны совпадать. Это не просто стиль — это закон для скринридеров.

Обработка ошибок с атрибутами

Когда пользователь вводит неверные данные, сообщение об ошибке должно быть связано с полем. Используйте aria-describedby:

<?php
$error = 'Введите корректный email';
echo '<input type="email" id="email" aria-describedby="email-error">';
echo '<span id="email-error" role="alert">' . htmlspecialchars($error) . '</span>';
?>

Атрибут role="alert" заставит скринридер немедленно прочитать ошибку, не дожидаясь, пока пользователь дойдёт до этого места.

Контрастность и цвета: не только CSS

Казалось бы, это задача дизайнера. Но если вы генерируете стили прямо из PHP (например, для кастомизации темы), нужно следить за контрастом. WCAG требует минимум 4.5:1 для обычного текста и 3:1 для крупного.

Пример проверки контрастности на PHP:

<?php
function getLuminance(string $hexColor): float {
    $hex = ltrim($hexColor, '#');
    $r = hexdec(substr($hex, 0, 2)) / 255;
    $g = hexdec(substr($hex, 2, 2)) / 255;
    $b = hexdec(substr($hex, 4, 2)) / 255;
    // Применяем формулу относительной яркости
    $r = ($r <= 0.03928) ? $r / 12.92 : pow(($r + 0.055) / 1.055, 2.4);
    $g = ($g <= 0.03928) ? $g / 12.92 : pow(($g + 0.055) / 1.055, 2.4);
    $b = ($b <= 0.03928) ? $b / 12.92 : pow(($b + 0.055) / 1.055, 2.4);
    return 0.2126 * $r + 0.7152 * $g + 0                

Блоги

Рекомендаций по книгам