Muuri — это библиотека для создания интерактивных сеток с поддержкой drag-and-drop, фильтрации и сортировки. Одним из важных аспектов работы с сеткой является управление фокусом элементов, что напрямую влияет на доступность, навигацию с клавиатуры и взаимодействие с пользователем. Muuri предоставляет гибкие механизмы для контроля фокуса и взаимодействия с элементами сетки.
В Muuri каждый элемент сетки (item) может быть
фокусируемым благодаря стандартным HTML-атрибутам. Для
того чтобы элемент мог получать фокус, необходимо:
<div class="item" tabindex="0">Элемент 1</div>
<div class="item" tabindex="0">Элемент 2</div>
tabindex="0" — делает элемент доступным для фокусировки
через клавишу Tab.tabindex="-1" — позволяет программно установить фокус
на элемент, но исключает его из последовательности табуляции.Muuri позволяет получать ссылку на объект элемента
через метод getItem или напрямую через массив
grid.getItems(), что важно для управления фокусом
программно.
const item = grid.getItems()[0];
item.getElement().focus();
Muuri предоставляет возможность отслеживать события фокуса и управлять им через API элементов. Основные методы:
item.getElement() — возвращает DOM-элемент.item.show() / item.hide() — отображение и
скрытие элемента с автоматическим сохранением позиции.item.getId() — идентификатор элемента для логики
фокусировки.Пример установки фокуса на первый видимый элемент:
const visibleItems = grid.getItems().filter(item => !item.isHidden());
if (visibleItems.length > 0) {
visibleItems[0].getElement().focus();
}
Для создания удобной навигации важно отслеживать события
focus и blur:
grid.getItems().forEach(item => {
const el = item.getElement();
el.addEventListener('focus', () => {
el.classList.add('focused');
});
el.addEventListener('blur', () => {
el.classList.remove('focused');
});
});
Muuri не ограничивает использование стандартных событий клавиатуры. С
помощью keydown можно реализовать навигацию между
элементами:
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowRight') {
const focused = document.activeElement;
const currentItemIndex = grid.getItems().findIndex(item => item.getElement() === focused);
const nextItem = grid.getItems()[currentItemIndex + 1];
if (nextItem) nextItem.getElement().focus();
}
});
При динамическом изменении сетки важно контролировать фокус, чтобы пользователь не потерял ориентацию:
grid.filter(item => item.getElement().textContent.includes('активный'));
const visibleItems = grid.getItems().filter(item => !item.isHidden());
if (visibleItems.length > 0) {
visibleItems[0].getElement().focus();
}
grid.getItems() гарантирует корректное управление
фокусом.Muuri позволяет реализовать drag-and-drop, и в этом случае важно корректно восстанавливать фокус:
grid.on('dragEnd', item => {
item.getElement().focus();
});
tabindex и обработкой клавиш можно
создать полностью клавиатурно-доступную сетку.Можно реализовать собственную логику фокусировки, например, перемещать фокус в зависимости от положения элемента:
function focusNearestItem(currentItem, direction) {
const allItems = grid.getItems().filter(i => !i.isHidden());
const currentRect = currentItem.getElement().getBoundingClientRect();
let nearestItem = null;
let minDistance = Infinity;
allItems.forEach(item => {
if (item === currentItem) return;
const rect = item.getElement().getBoundingClientRect();
const distance = Math.hypot(rect.left - currentRect.left, rect.top - currentRect.top);
if (distance < minDistance) {
minDistance = distance;
nearestItem = item;
}
});
if (nearestItem) nearestItem.getElement().focus();
}
tabindex="0" или быть
естественно фокусируемыми (button, a,
input).grid.getItems() для получения актуального списка
элементов.focus и blur для
визуальной подсветки активного элемента.Эти подходы обеспечивают полный контроль над фокусом в сетках Muuri, повышают доступность интерфейса и создают более интуитивное взаимодействие с элементами.