Реалізація режиму підвищеної доступності на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація режиму підвищеної доступності на сайті
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація режиму повищеної доступності на сайті

Режим повищеної доступності — перемикач, який застосовує набір додаткових поліпшень інтерфейсу: збільшений шрифт, підвищений контраст, спрощена анімація, поліпшені індикатори фокуса. Дозволяє не навязувати зміни всім користувачам, залишаючи вибір тим, кому це потрібно.

Компоненти режиму доступності

Типовий набір опцій:

  • Висококонтрастна тема (контраст 7:1+)
  • Збільшений шрифт (+2–4px базовий розмір)
  • Відключення анімації (prefers-reduced-motion)
  • Збільшені зони кліку
  • Більш помітний індикатор фокуса
  • Спрощений layout (один стовпець)

CSS-змінні як основа

/* Базові змінні */
:root {
    --font-size-base: 16px;
    --color-text: #333333;
    --color-bg: #ffffff;
    --color-accent: #0056b3;
    --focus-outline: 2px solid #0056b3;
    --focus-outline-offset: 2px;
    --transition-duration: 300ms;
    --min-touch-target: 44px;
}

/* Режим високого контрасту */
[data-accessibility-mode~="high-contrast"] {
    --color-text:   #000000;
    --color-bg:     #ffffff;
    --color-accent: #0000CC;
    --focus-outline: 3px solid #000000;
    --focus-outline-offset: 4px;
}

/* Збільшений шрифт */
[data-accessibility-mode~="large-text"] {
    --font-size-base: 20px;
}

/* Зменшення анімації */
[data-accessibility-mode~="reduced-motion"],
@media (prefers-reduced-motion: reduce) {
    --transition-duration: 0ms;
    * {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

/* Збільшені цілі касання */
[data-accessibility-mode~="large-targets"] {
    --min-touch-target: 56px;
    a, button, [role="button"] {
        min-height: var(--min-touch-target);
        min-width: var(--min-touch-target);
        display: inline-flex;
        align-items: center;
    }
}

React компонент управління режимом

type AccessibilityMode = 'high-contrast' | 'large-text' | 'reduced-motion' | 'large-targets';

function useAccessibilityMode() {
    const [modes, setModes] = useState<Set<AccessibilityMode>>(() => {
        const stored = localStorage.getItem('a11y-modes');
        return stored ? new Set(JSON.parse(stored)) : new Set();
    });

    // Враховуємо системні настройки
    useEffect(() => {
        const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
        if (mediaQuery.matches) {
            setModes(prev => new Set([...prev, 'reduced-motion']));
        }
    }, []);

    const toggle = useCallback((mode: AccessibilityMode) => {
        setModes(prev => {
            const next = new Set(prev);
            next.has(mode) ? next.delete(mode) : next.add(mode);
            localStorage.setItem('a11y-modes', JSON.stringify([...next]));
            return next;
        });
    }, []);

    // Застосувати до document.documentElement
    useEffect(() => {
        document.documentElement.dataset.accessibilityMode = [...modes].join(' ');
    }, [modes]);

    return { modes, toggle };
}

function AccessibilityPanel() {
    const { modes, toggle } = useAccessibilityMode();
    const [isOpen, setIsOpen] = useState(false);

    const options = [
        { id: 'high-contrast' as const,  label: 'Високий контраст', icon: '◑' },
        { id: 'large-text' as const,     label: 'Збільшений текст', icon: 'A+' },
        { id: 'reduced-motion' as const, label: 'Менше анімації',   icon: '⏸' },
        { id: 'large-targets' as const,  label: 'Крупні кнопки',    icon: '⊞' },
    ];

    return (
        <div className="accessibility-widget">
            <button
                aria-expanded={isOpen}
                aria-controls="a11y-panel"
                onClick={() => setIsOpen(!isOpen)}
                aria-label="Настройки доступності"
            >
                ♿
            </button>

            {isOpen && (
                <div id="a11y-panel" role="group" aria-label="Настройки доступності">
                    {options.map(opt => (
                        <label key={opt.id} className="a11y-option">
                            <input
                                type="checkbox"
                                checked={modes.has(opt.id)}
                                onChange={() => toggle(opt.id)}
                            />
                            <span className="icon">{opt.icon}</span>
                            {opt.label}
                        </label>
                    ))}

                    <button
                        onClick={() => {
                            localStorage.removeItem('a11y-modes');
                            setModes(new Set());
                        }}
                    >
                        Скинути настройки
                    </button>
                </div>
            )}
        </div>
    );
}

Системні медіа-запити (без JS)

Частина настроєк застосовується автоматично з системних настроєк:

/* Автоматично для користувачів, які вибрали зменшення анімації в ОС */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* Системна висококонтрастна тема */
@media (prefers-contrast: more) {
    :root {
        --color-text: #000;
        --color-bg: #fff;
        --focus-outline: 3px solid #000;
    }
}

/* Темна тема */
@media (prefers-color-scheme: dark) {
    :root {
        --color-text: #f0f0f0;
        --color-bg: #1a1a1a;
    }
}

Позиціонування віджета

Віджет доступності зазвичай розміщується у фіксованій позиції:

.accessibility-widget {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 9000;
}

Важливо: віджет сам повинен бути доступен з клавіатури — інакше користувачі, яким він потрібен, не зможуть ним користуватися.

Часові рамки

3–5 днів: система CSS-змінних + React-компонент + тестування кожного режиму з екранною читалкою.