Какие события отлавливают фокус?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Управление фокусом в DOM: события и их применение
В веб-разработке управление фокусом — критически важный аспект доступности (a11y) и пользовательского опыта. Браузер предоставляет несколько событий фокуса, которые позволяют отслеживать и реагировать на изменения в активном элементе страницы. Рассмотрим основные события и их особенности.
Основные события фокуса
1. focus и focusin
Событие focus возникает, когда элемент получает фокус (например, при клике мышью, переходе по Tab, или программном вызове .focus()). Важное отличие: focus не всплывает (non-bubbling).
// Пример с focus (не всплывает)
const input = document.querySelector('input');
input.addEventListener('focus', (event) => {
console.log('Элемент получил фокус', event.target);
});
// focusin — всплывающий аналог
document.addEventListener('focusin', (event) => {
console.log('Фокус внутри документа на:', event.target);
});
Событие focusin является всплывающим аналогом focus и позволяет отлавливать фокус на уровне родительских элементов.
2. blur и focusout
Противоположные события возникают при потере фокусa:
blur— не всплываетfocusout— всплывает
// Отслеживание потери фокуса
input.addEventListener('blur', () => {
console.log('Проверка ввода при потере фокуса');
validateInput(input.value);
});
// Всплывающая версия
form.addEventListener('focusout', (event) => {
if (event.target.tagName === 'INPUT') {
console.log('Поле вышло из фокуса');
}
});
Практическое применение событий фокуса
Валидация форм
События фокуса идеально подходят для инлайн-валидации полей ввода:
const emailInput = document.getElementById('email');
emailInput.addEventListener('blur', () => {
const isValid = validateEmail(emailInput.value);
if (!isValid) {
showError('Введите корректный email');
emailInput.focus(); // Возвращаем фокус на поле с ошибкой
}
});
Улучшение доступности
Для пользователей скринридеров важно правильно управлять фокусом при динамических изменениях:
// Перемещение фокуса при открытии модального окна
function openModal() {
modal.style.display = 'block';
modal.focus(); // Передаем фокус модальному окну
modal.setAttribute('tabindex', '-1'); // Делаем фокусируемым
}
// Возврат фокуса при закрытии
function closeModal() {
modal.style.display = 'none';
lastFocusedElement.focus(); // Возвращаем фокус на предыдущий элемент
}
Управление фокусом в SPA
В одностраничных приложениях важно правильно восстанавливать фокус при навигации:
// Запоминаем текущий элемент с фокусом
let previousFocus = null;
router.beforeEach((to, from, next) => {
previousFocus = document.activeElement;
next();
});
router.afterEach(() => {
// После смены маршрута проверяем, нужен ли фокус на новом элементе
const mainHeading = document.querySelector('h1');
if (mainHeading) {
mainHeading.setAttribute('tabindex', '-1');
mainHeading.focus();
}
});
Советы по работе с фокусом
- Используйте делегирование событий через
focusin/focusoutдля эффективной обработки - Избегайте блокировки фокуса без веской причины — это нарушает доступность
- Тестируйте с клавиатуры — убедитесь, что все интерактивные элементы доступны через Tab
- Учитывайте порядок табуляции при динамическом добавлении элементов
- Используйте
tabindexосмотрительно:tabindex="0"— элемент в естественном порядке табуляцииtabindex="-1"— элемент фокусируем программно, но не через Tabtabindex > 0— избегайте, это нарушает естественный порядок
Расширенные сценарии
Кастомные элементы управления
Для создания кастомных элементов (например, виджета с вкладками) необходимо тщательно управлять фокусом:
class TabWidget {
constructor(container) {
this.tabs = container.querySelectorAll('.tab');
this.panels = container.querySelectorAll('.panel');
this.setupFocusManagement();
}
setupFocusManagement() {
this.tabs.forEach((tab, index) => {
tab.addEventListener('keydown', (event) => {
if (event.key === 'ArrowRight') {
// Перемещение фокуса на следующую вкладку
this.tabs[(index + 1) % this.tabs.length].focus();
}
});
});
}
}
Отслеживание траектории фокуса
Иногда необходимо знать весь путь перемещения фокуса:
const focusPath = [];
document.addEventListener('focusin', (event) => {
focusPath.push({
element: event.target.tagName,
id: event.target.id,
timestamp: Date.now()
});
// Ограничиваем историю
if (focusPath.length > 10) {
focusPath.shift();
}
});
Правильная работа с событиями фокуса — ключевой навык для создания доступных и удобных веб-интерфейсов. Она требует внимания к деталям, но значительно улучшает пользовательский опыт для всех, особенно для людей с ограниченными возможностями.