Современные веб-интерфейсы должны одинаково корректно работать при использовании различных способов ввода: клавиатуры, мыши, сенсорного экрана, стилуса и других указательных устройств. Однако визуальная обратная связь, которая уместна при работе с клавиатурой, может выглядеть избыточной или даже мешающей при использовании мыши.
Наиболее распространённый пример — фокусные контуры (focus outlines). При навигации клавиатурой фокус необходим для понимания текущего положения в интерфейсе. При клике мышью эти контуры часто воспринимаются как визуальный шум.
Разработчики нередко решают эту проблему отключением стиля
outline, что приводит к ухудшению доступности. Пользователи
клавиатуры теряют ориентиры навигации, а интерфейс становится трудным
для использования.
Библиотека ally.js предоставляет инструменты, позволяющие условно применять стили в зависимости от способа взаимодействия, не нарушая доступность.
По умолчанию браузеры применяют фокусный стиль к интерактивным элементам:
button:focus {
outline: auto;
}
При клике мышью этот стиль также появляется. Чтобы избежать этого, многие проекты используют правило:
:focus {
outline: none;
}
Подобный подход считается анти-паттерном доступности, поскольку:
Необходимо различать программный фокус, фокус клавиатуры и фокус после клика мышью.
Библиотека ally.js предоставляет модуль focus-source, который отслеживает источник возникновения фокуса.
Основная задача модуля — определить, каким способом был установлен фокус:
element.focus().В зависимости от этого источника можно применять разные CSS-классы или стили.
Модуль focus-source анализирует события
пользовательского ввода:
keydownmousedowntouchstartfocusПоследовательность событий позволяет определить, каким действием был вызван фокус.
Пример подключения:
import focusSource from 'ally.js/observe/focus-source';
const handle = focusSource();
После инициализации библиотека начинает отслеживать взаимодействие пользователя.
Получить текущий источник фокуса можно через состояние модуля:
console.log(handle.get());
Возможные значения:
| значение | описание |
|---|---|
keyboard |
фокус установлен клавиатурой |
mouse |
фокус установлен мышью |
touch |
сенсорное взаимодействие |
script |
программный вызов |
Эта информация используется для управления визуальным состоянием интерфейса.
Часто применяется подход, при котором библиотека добавляет класс на корневой элемент документа.
Пример реализации:
import focusSource from 'ally.js/observe/focus-source';
focusSource({
context: document.documentElement
});
После этого на <html> добавляются классы:
ally-focus-source-keyboard
ally-focus-source-mouse
ally-focus-source-touch
ally-focus-source-script
Классы автоматически обновляются при изменении способа взаимодействия.
Использование CSS-классов позволяет гибко управлять отображением фокуса.
:focus {
outline: none;
}
.ally-focus-source-keyboard :focus {
outline: 3px solid #3b82f6;
}
Поведение:
Tab) контур
отображается.Этот подход сохраняет доступность и избавляет от лишних визуальных эффектов.
Для пользователей клавиатуры фокус должен быть максимально заметным.
.ally-focus-source-keyboard button:focus {
outline: 3px solid #2563eb;
outline-offset: 2px;
}
Дополнительный outline-offset позволяет избежать
наложения на границы элементов.
Сенсорные интерфейсы часто требуют более крупных визуальных индикаторов.
.ally-focus-source-touch :focus {
outline: 4px solid #10b981;
}
Такой подход особенно полезен для гибридных устройств.
Источник фокуса можно использовать не только для CSS, но и для изменения поведения компонентов.
Меню может реагировать по-разному в зависимости от метода взаимодействия.
Навигация клавиатурой:
Навигация мышью:
Определение источника фокуса:
const handle = focusSource();
document.addEventListener('focusin', (event) => {
if (handle.get() === 'keyboard') {
openMenu(event.target);
}
});
Иногда фокус устанавливается через Jav * aScript:
input.focus();
Такой фокус получает источник script.
Это важно учитывать в следующих случаях:
Для таких ситуаций можно задать отдельные стили:
.ally-focus-source-script :focus {
outline: 2px dashed #6b7280;
}
:focus-visibleСовременные браузеры поддерживают псевдокласс:
:focus-visible
Он автоматически отображает фокус только при навигации клавиатурой.
Пример:
:focus:not(:focus-visible) {
outline: none;
}
Однако поддержка не во всех браузерах одинакова, особенно в старых версиях.
Преимущества ally.js:
Модуль focus-source часто используется вместе с другими
инструментами библиотеки.
ally.maintain.tabFocusКонтроль последовательности фокуса внутри модальных окон.
ally.query.focusableОпределение элементов, которые могут получать фокус.
ally.when.focusableОжидание появления фокусируемых элементов в DOM.
Комбинирование этих модулей позволяет создавать интерфейсы с корректной доступностью и адаптивным поведением.
Модуль отслеживания источника фокуса использует минимальный набор глобальных обработчиков:
keydownmousedowntouchstartfocusОбработка выполняется на уровне документа, что снижает нагрузку и не требует добавления слушателей к каждому элементу интерфейса.
Обновление CSS-классов происходит только при изменении источника ввода, что предотвращает лишние перерисовки.
Часто применяется следующий шаблон:
focus-source.<html>.Инициализация:
import focusSource from 'ally.js/observe/focus-source';
focusSource({
context: document.documentElement
});
CSS:
:focus {
outline: none;
}
.ally-focus-source-keyboard :focus {
outline: 3px solid #2563eb;
}
Результат:
Разделение способов взаимодействия позволяет:
Условные стили на основе источника фокуса являются важным элементом построения доступных пользовательских интерфейсов и широко применяются в современных фронтенд-архитектурах.