Isotope — мощная библиотека для динамической сортировки и фильтрации элементов на веб-странице. Комбинированная фильтрация позволяет одновременно применять несколько критериев фильтрации, создавая гибкую систему отображения элементов. Этот подход особенно полезен для каталогов, галерей, списков товаров и любых интерфейсов с множественными фильтрами.
Комбинированная фильтрация основывается на двух ключевых моментах:
Isotope использует метод filter, которому можно
передавать функцию или CSS-селектор. Для комбинированной фильтрации чаще
всего применяется функция, которая проверяет несколько условий.
Фильтры обычно группируются по категориям. Пример структуры HTML:
<div class="filters">
<div class="filter-group" data-filter-group="color">
<button data-filter="*">Все цвета</button>
<button data-filter=".red">Красный</button>
<button data-filter=".blue">Синий</button>
</div>
<div class="filter-group" data-filter-group="type">
<button data-filter="*">Все типы</button>
<button data-filter=".shirt">Футболки</button>
<button data-filter=".pants">Штаны</button>
</div>
</div>
<div class="grid">
<div class="grid-item red shirt">Футболка красная</div>
<div class="grid-item blue pants">Штаны синие</div>
<div class="grid-item red pants">Штаны красные</div>
</div>
Каждая группа фильтров имеет атрибут data-filter-group,
а каждая кнопка — свой data-filter. Такой подход позволяет
хранить состояние фильтров и применять их комбинированно.
Для работы с фильтрацией создаётся экземпляр Isotope:
var iso = new Isotope('.grid', {
itemSelector: '.grid-item',
layoutMode: 'fitRows'
});
Здесь itemSelector указывает элементы, которые будут
сортироваться и фильтроваться, а layoutMode определяет
алгоритм расположения элементов (fitRows или
masonry).
Комбинированная фильтрация требует хранения активных фильтров для каждой группы и объединения их при применении:
var filters = {};
var filterGroups = document.querySelectorAll('.filter-group');
filterGroups.forEach(function(group) {
group.addEventListener('click', function(event) {
if (!event.target.matches('button')) return;
var filterGroup = group.getAttribute('data-filter-group');
filters[filterGroup] = event.target.getAttribute('data-filter');
// Объединяем фильтры
var filterValue = concatFilters(filters);
iso.arrange({ filter: filterValue });
});
});
function concatFilters(filters) {
var allFilters = Object.values(filters);
return allFilters.join('');
}
Функция concatFilters объединяет фильтры через
конкатенацию CSS-классов. Если значение фильтра *, оно не
влияет на результат.
Для более сложных условий можно использовать функцию:
iso.arrange({
filter: function(itemElem) {
var colorFilter = filters.color || '*';
var typeFilter = filters.type || '*';
var matchesColor = colorFilter === '*' || itemElem.classList.contains(colorFilter.substring(1));
var matchesType = typeFilter === '*' || itemElem.classList.contains(typeFilter.substring(1));
return matchesColor && matchesType;
}
});
Такой подход позволяет гибко проверять условия, включая диапазоны чисел, текстовые соответствия или любые пользовательские критерии.
Для улучшения UX полезно подсвечивать активные фильтры:
var buttons = document.querySelectorAll('.filter-group button');
buttons.forEach(function(btn) {
btn.addEventListener('click', function() {
var siblings = btn.parentNode.querySelectorAll('button');
siblings.forEach(function(sib) { sib.classList.remove('is-checked'); });
btn.classList.add('is-checked');
});
});
Класс is-checked визуально отмечает выбранный фильтр,
обеспечивая понятное взаимодействие с пользователем.
Isotope поддерживает плавную анимацию при фильтрации и сортировке:
iso.arrange({
filter: concatFilters(filters),
transitionDuration: '0.6s'
});
Параметр transitionDuration задаёт скорость анимации,
что делает интерфейс более плавным и современным.
Комбинированная фильтрация может включать несколько групп и исключения:
:not()
в селекторах, чтобы исключить элементы.Пример исключения:
iso.arrange({ filter: '.shirt:not(.red)' });
Отобразятся все футболки, кроме красных.
При добавлении новых элементов через AJAX или динамически необходимо
вызвать appended:
var newItems = document.querySelectorAll('.grid-item-new');
iso.appended(newItems);
iso.arrange({ filter: concatFilters(filters) });
Это гарантирует, что новые элементы будут учитывать текущие фильтры.
* как универсальный фильтр, чтобы можно
было сбрасывать группы.requestAnimationFrame для плавности анимации.Комбинированная фильтрация в Isotope позволяет создавать мощные и интерактивные интерфейсы с гибкими условиями отображения элементов, управляемыми через кнопки, селекторы и динамический контент.