Packery — это библиотека для создания динамических сеток с возможностью перестройки элементов, которая опирается на концепцию позиционирования по свободной сетке. Важным аспектом при работе с интерактивными элементами сетки является корректная обработка фокуса и передвижения с помощью клавиши Tab, чтобы обеспечить доступность и предсказуемое поведение элементов при навигации с клавиатуры.
В стандартных HTML-структурах фокус на элемент может быть установлен
через атрибут tabindex. Packery не изменяет поведение
фокуса сам по себе, но при динамическом перемещении элементов внутри
контейнера важно учитывать, что:
tabindex.tabindex<div class="grid">
<div class="grid-item" tabindex="0">Элемент 1</div>
<div class="grid-item" tabindex="0">Элемент 2</div>
<div class="grid-item" tabindex="0">Элемент 3</div>
</div>
При динамическом перемещении элементов с помощью Packery их
tabindex не меняется, что может приводить к неестественной
последовательности при навигации. Чтобы этого избежать, можно программно
корректировать порядок табуляции:
const gridItems = document.querySelectorAll('.grid-item');
gridItems.forEach((item, index) => {
item.setAttribute('tabindex', index + 1);
});
Packery управляет позиционированием элементов, но стандартный Tab-переход следует естественному порядку DOM. При интерактивных интерфейсах с возможностью перетаскивания важно:
keydown для контроля
фокуса, если визуальное расположение элементов отличается от их
порядка в DOM.Пример переопределения поведения Tab для сетки Packery:
document.querySelector('.grid').addEventListener('keydown', (event) => {
if (event.key === 'Tab') {
const items = Array.from(document.querySelectorAll('.grid-item'));
const currentIndex = items.indexOf(document.activeElement);
let nextIndex = event.shiftKey ? currentIndex - 1 : currentIndex + 1;
if (nextIndex >= items.length) nextIndex = 0;
if (nextIndex < 0) nextIndex = items.length - 1;
items[nextIndex].focus();
event.preventDefault();
}
});
Такой подход обеспечивает логическую циклическую навигацию, вне зависимости от того, как Packery разместил элементы визуально.
Packery часто используется вместе с библиотеками для перетаскивания
элементов, например, Draggabilly. При этом важно
учитывать:
const pckry = new Packery('.grid', {
itemSelector: '.grid-item',
gutter: 10
});
pckry.getItemElements().forEach(itemElem => {
const draggie = new Draggabilly(itemElem);
draggie.on('dragEnd', () => {
itemElem.focus();
});
});
Такой подход обеспечивает плавный переход фокуса, минимизируя потерю ориентировки для пользователей клавиатуры.
Для полной доступности сетки необходимо:
role="grid" и
role="gridcell" к контейнеру и элементам
соответственно.aria-label или
aria-labelledby для элементов, чтобы сообщать их
содержимое экранным читалкам.document.querySelector('.grid').addEventListener('keydown', (event) => {
const items = Array.from(document.querySelectorAll('.grid-item'));
const currentIndex = items.indexOf(document.activeElement);
if (event.key === 'ArrowRight') {
const nextIndex = (currentIndex + 1) % items.length;
items[nextIndex].focus();
event.preventDefault();
}
if (event.key === 'ArrowLeft') {
const prevIndex = (currentIndex - 1 + items.length) % items.length;
items[prevIndex].focus();
event.preventDefault();
}
});
Такое управление обеспечивает естественное перемещение по сетке, соответствующее визуальному расположению элементов.
Packery поддерживает динамическое добавление и удаление элементов
через методы appended и remove. Для сохранения
логики табуляции:
const newItem = document.createElement('div');
newItem.className = 'grid-item';
newItem.setAttribute('tabindex', 0);
newItem.textContent = 'Новый элемент';
grid.appendChild(newItem);
pckry.appended(newItem);
// Пересчёт tabindex для всей сетки
const gridItems = document.querySelectorAll('.grid-item');
gridItems.forEach((item, index) => item.setAttribute('tabindex', index + 1));
Такой подход гарантирует, что добавленные элементы становятся частью последовательности навигации, а пользователи не теряют ориентацию при работе с клавиатурой.
В больших сетках стоит:
tabindex="-1" для невидимых
элементов, чтобы они не попадали в последовательность Tab.Эти методы позволяют Packery корректно работать с фокусом и табуляцией, обеспечивая доступность, предсказуемую навигацию и контроль над взаимодействием клавиатуры с сеткой.