Пост

Доступность веб-приложений: создание инклюзивного интернета

Подробное руководство по созданию доступных веб-приложений. Изучите принципы доступности, ARIA-атрибуты и лучшие практики для создания инклюзивного интернета.

Доступность веб-приложений: создание инклюзивного интернета

Введение

Доступность (Accessibility) - это принцип, согласно которому веб-приложения должны быть доступны для всех пользователей, независимо от их физических или когнитивных возможностей. В этой статье мы рассмотрим основные принципы и практики создания доступных веб-приложений.

Почему важна доступность?

  • Инклюзивность: Доступ для всех пользователей
  • Юридические требования: Соответствие законодательству
  • Бизнес-выгода: Расширение аудитории
  • Этика: Социальная ответственность

Основные принципы доступности

1. Воспринимаемость

Семантическая разметка

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- Правильная семантическая структура -->
<header>
    <nav aria-label="Основное меню">
        <ul>
            <li><a href="/">Главная</a></li>
            <li><a href="/about">О нас</a></li>
            <li><a href="/contact">Контакты</a></li>
        </ul>
    </nav>
</header>

<main>
    <article>
        <h1>Заголовок статьи</h1>
        <p>Содержание статьи...</p>
    </article>
</main>

2. Понятность

Четкая структура контента

1
2
3
4
5
6
7
8
9
10
11
<!-- Структурированный контент -->
<section aria-labelledby="section-title">
    <h2 id="section-title">Название раздела</h2>
    <div class="content">
        <p>Основной текст...</p>
        <aside>
            <h3>Дополнительная информация</h3>
            <p>Дополнительный контент...</p>
        </aside>
    </div>
</section>

ARIA-атрибуты

1. Основные ARIA-роли

Использование ролей

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- Примеры ARIA-ролей -->
<div role="banner">
    <h1>Логотип сайта</h1>
</div>

<div role="navigation" aria-label="Основное меню">
    <ul>
        <li><a href="/">Главная</a></li>
        <li><a href="/about">О нас</a></li>
    </ul>
</div>

<div role="main">
    <article>
        <h2>Основной контент</h2>
        <p>Текст статьи...</p>
    </article>
</div>

2. ARIA-состояния и свойства

Управление состоянием

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- Примеры ARIA-состояний -->
<button 
    aria-expanded="false"
    aria-controls="dropdown-menu"
    aria-haspopup="true">
    Меню
</button>

<div 
    id="dropdown-menu"
    role="menu"
    aria-hidden="true">
    <a href="#" role="menuitem">Пункт 1</a>
    <a href="#" role="menuitem">Пункт 2</a>
</div>

Формы и валидация

1. Доступные формы

Структура формы

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<form aria-labelledby="form-title">
    <h2 id="form-title">Регистрация</h2>
    
    <div class="form-group">
        <label for="name">Имя:</label>
        <input 
            type="text"
            id="name"
            name="name"
            required
            aria-required="true"
            aria-describedby="name-error">
        <div id="name-error" class="error" role="alert"></div>
    </div>
    
    <button type="submit">Отправить</button>
</form>

2. Валидация и обратная связь

Обработка ошибок

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Валидация формы
function validateForm(event) {
    const form = event.target;
    const nameInput = form.querySelector('#name');
    const errorDiv = form.querySelector('#name-error');
    
    if (!nameInput.value.trim()) {
        errorDiv.textContent = 'Пожалуйста, введите имя';
        nameInput.setAttribute('aria-invalid', 'true');
        return false;
    }
    
    errorDiv.textContent = '';
    nameInput.setAttribute('aria-invalid', 'false');
    return true;
}

Клавиатурная навигация

1. Управление фокусом

Настройка фокуса

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Управление фокусом
function handleFocus() {
    const focusableElements = document.querySelectorAll(
        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    
    focusableElements.forEach(element => {
        element.addEventListener('focus', () => {
            element.classList.add('focus-visible');
        });
        
        element.addEventListener('blur', () => {
            element.classList.remove('focus-visible');
        });
    });
}

2. Стили фокуса

CSS для фокуса

1
2
3
4
5
6
7
8
9
10
/* Стили для фокуса */
.focus-visible {
    outline: 2px solid #007bff;
    outline-offset: 2px;
}

/* Скрытие фокуса только для мыши */
:focus:not(:focus-visible) {
    outline: none;
}

Мультимедиа и альтернативный контент

1. Изображения

Альтернативный текст

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Правильное использование alt -->
<img 
    src="logo.png"
    alt="Логотип компании Example Corp"
    width="150"
    height="50">

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

2. Видео и аудио

Доступные медиа-элементы

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Видео с субтитрами -->
<video controls>
    <source src="video.mp4" type="video/mp4">
    <track 
        kind="subtitles" 
        src="subtitles.vtt" 
        srclang="ru" 
        label="Русские субтитры"
        default>
    <p>Ваш браузер не поддерживает видео.</p>
</video>

<!-- Аудио с транскрипцией -->
<audio controls>
    <source src="audio.mp3" type="audio/mpeg">
    <p>
        <a href="transcript.txt">Скачать транскрипцию</a>
    </p>
</audio>

Тестирование доступности

1. Автоматизированное тестирование

Использование инструментов

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Пример использования axe-core
import axe from 'axe-core';

function runAccessibilityTests() {
    axe.run(document.body, {
        rules: {
            'color-contrast': { enabled: true },
            'document-title': { enabled: true }
        }
    }).then(results => {
        if (results.violations.length > 0) {
            console.error('Найдены проблемы доступности:', results.violations);
        }
    });
}

2. Ручное тестирование

Чек-лист проверки

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Чек-лист для ручного тестирования
const accessibilityChecklist = {
    keyboardNavigation: () => {
        // Проверка навигации с клавиатуры
        return document.querySelectorAll(':focus-visible').length > 0;
    },
    
    colorContrast: () => {
        // Проверка контрастности цветов
        return checkColorContrast();
    },
    
    screenReader: () => {
        // Проверка работы с программами чтения с экрана
        return testScreenReaderCompatibility();
    }
};

Заключение

Создание доступных веб-приложений - это не только требование законодательства, но и важный аспект создания качественного пользовательского опыта. Следуйте принципам доступности и регулярно тестируйте ваше приложение на соответствие стандартам.

Авторский пост защищен лицензией CC BY 4.0 .

© Oleg Dobrynin. Некоторые права защищены.