Реалізація режиму повищеної доступності на сайті
Режим повищеної доступності — перемикач, який застосовує набір додаткових поліпшень інтерфейсу: збільшений шрифт, підвищений контраст, спрощена анімація, поліпшені індикатори фокуса. Дозволяє не навязувати зміни всім користувачам, залишаючи вибір тим, кому це потрібно.
Компоненти режиму доступності
Типовий набір опцій:
- Висококонтрастна тема (контраст 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-компонент + тестування кожного режиму з екранною читалкою.







