You can add fast, client-side search and multi-tag filtering to a Webflow Collection List with a few data attributes and a small vanilla JS module published from Slater.
What you’ll build
Assumed markup (Designer)
Vanilla JS module (paste into a Slater file)
(function initCmsFilter() {const root = document.querySelector('[data-cms="list"]');if (!root) return; // page doesn’t have the listif (root.dataset.inited) return; // avoid double init root.dataset.inited = '1';const items = Array.from(root.querySelectorAll('[data-cms="item"]'));const state = { q: '', tags: new Set() };function itemMatches(el) {const text = el.textContent.toLowerCase();if (state.q && !text.includes(state.q)) return false;if (state.tags.size) {const tags = (el.dataset.tags || '') .toLowerCase() .split(',') .map(s => s.trim()) .filter(Boolean);for (const t of state.tags) if (!tags.includes(t)) return false; // AND logic }return true; }function render() {for (const el of items) el.style.display = itemMatches(el) ? '' : 'none'; }const search = document.querySelector('[data-filter="search"]');if (search) search.addEventListener('input', (e) => {state.q = e.target.value.toLowerCase().trim();render(); }); document.addEventListener('change', (e) => {const cb = e.target;if (cb && cb.matches('[data-filter="tag"]')) {const v = (cb.value || '').toLowerCase();cb.checked ? state.tags.add(v) : state.tags.delete(v);render(); } });render();})();Optional: sorting (A→Z)
(function addSortAZ() {const root = document.querySelector('[data-cms="list"]');const sortBtn = document.querySelector('[data-sort="az"]');if (!root || !sortBtn) return;const wrapper = root.parentElement; // container that holds the listsortBtn.addEventListener('click', () => {const items = Array.from(root.querySelectorAll('[data-cms="item"]')) .sort((a, b) => a.textContent.localeCompare(b.textContent));const frag = document.createDocumentFragment();items.forEach(i => frag.appendChild(i));root.appendChild(frag); });})();Performance and UX tips
Publishing
FAQ