Управление фокусом — критически важная часть работы модальных окон. Featherlight, как минималистичная lightbox-библиотека, не перегружена сложной инфраструктурой доступности, однако предоставляет достаточные механизмы для корректного контроля фокуса при открытии и закрытии модальных окон. Неправильная работа с фокусом приводит к проблемам навигации с клавиатуры, ухудшает доступность и может вызывать логические ошибки в интерфейсе.
В контексте Featherlight под фокусом понимается активный DOM-элемент, получающий ввод с клавиатуры и участвующий в таб-навигации.
При открытии lightbox Featherlight выполняет следующие действия:
.featherlight.featherlight-contentЭто означает, что:
Такое поведение осознанно: Featherlight не навязывает стратегию управления фокусом и оставляет её на уровне реализации.
Корректная стратегия — переводить фокус внутрь модального окна сразу после его открытия. Featherlight предоставляет для этого события жизненного цикла.
Ключевые события:
featherlight-openedafterOpen (опция)Пример установки фокуса на первый интерактивный элемент:
$.featherlight(content, {
afterOpen: function() {
this.$content
.find('input, button, select, textarea, a[href]')
.first()
.focus();
}
});
Ключевые моменты:
this.$content, а не поиск по
documentЕсли контент не содержит интерактивных элементов, контейнер можно сделать фокусируемым вручную:
<div class="modal-content" tabindex="-1">
...
</div>
И затем:
afterOpen: function() {
this.$content.focus();
}
Это позволяет:
Featherlight не реализует focus trap из коробки. Для полноценного управления фокусом требуется ручная реализация.
Базовый принцип:
keydown для клавиши TabПример логики:
afterOpen: function() {
const $focusable = this.$content.find(
'a[href], button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
);
const first = $focusable.first();
const last = $focusable.last();
this.$instance.on('keydown', function(e) {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first[0]) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last[0]) {
e.preventDefault();
first.focus();
}
}
});
first.focus();
}
Здесь используется:
$instance — корневой элемент FeatherlightХорошей практикой является возврат фокуса на элемент, который был активен до открытия модального окна.
Алгоритм:
document.activeElement перед открытиемПример:
let lastFocusedElement;
$(document).on('click', '.open-modal', function() {
lastFocusedElement = document.activeElement;
$.featherlight('#modal');
});
$(document).on('featherlight-closed', function() {
if (lastFocusedElement) {
lastFocusedElement.focus();
}
});
Это особенно важно:
Featherlight по умолчанию закрывается по Esc. При
этом:
featherlight-closed срабатывает всегдаЕсли реализован focus trap, важно:
Рекомендуется очищать все связанные слушатели в
afterClose:
afterClose: function() {
this.$instance.off('keydown');
}
При загрузке контента через AJAX или при динамическом обновлении DOM внутри lightbox:
Решение:
Пример для AJAX-контента:
$.featherlight({
ajax: '/modal.html',
afterOpen: function() {
const fl = this;
setTimeout(function() {
fl.$content.find('input').first().focus();
}, 0);
}
});
Featherlight допускает открытие одного lightbox поверх другого. В этом случае управление фокусом усложняется:
Практика:
$instanceОтсутствие установки фокуса
Фокус на скрытом элементе
Глобальные обработчики keydown
Использование autofocus в HTML
Хотя Featherlight не является accessibility-фреймворком, корректное управление фокусом позволяет:
Фокус в Featherlight — не автоматическая функция, а архитектурная ответственность разработчика. Именно поэтому понимание жизненного цикла lightbox и точек управления фокусом является обязательным при использовании библиотеки в серьёзных интерфейсах.