DEV Community

Dylan Parker
Dylan Parker

Posted on

So you’ve built a shopping site with a nice collection of women’s jeans

Now you want to display them in a way that actually makes people want to browse. A static list just doesn’t cut it anymore. Users expect interactivity, and a solid filter system can turn a flat product grid into an engaging experience.

Let’s build a simple, client-side JavaScript filter for your jeans collection. No frameworks, no libraries—just vanilla JS that works anywhere.

First, structure your HTML. Give each product card a data attribute for its category (like "skinny", "bootcut", "high-waist") and its size availability.

<div id="jeans-grid">
  <div class="product-card" data-category="skinny" data-size="26">
    <img src="jean1.jpg" alt="Skinny Jean">
    <h3>Classic Skinny</h3>
    <p>$49.99</p>
  </div>
  <div class="product-card" data-category="bootcut" data-size="28">
    <img src="jean2.jpg" alt="Bootcut Jean">
    <h3>Flared Comfort</h3>
    <p>$59.99</p>
  </div>
  <!-- Add more products -->
</div>
Enter fullscreen mode Exit fullscreen mode

Now, create the filter controls. A set of buttons for categories, plus a range input or dropdown for sizes.

<div id="filters">
  <button data-filter="all">All</button>
  <button data-filter="skinny">Skinny</button>
  <button data-filter="bootcut">Bootcut</button>
  <button data-filter="high-waist">High Waist</button>
  <select id="size-filter">
    <option value="all">All Sizes</option>
    <option value="26">26</option>
    <option value="28">28</option>
    <option value="30">30</option>
  </select>
</div>
Enter fullscreen mode Exit fullscreen mode

Here’s the JavaScript that brings it to life. It listens for clicks on the category buttons and changes on the size dropdown, then hides or shows products accordingly.

const products = document.querySelectorAll('.product-card');
const categoryButtons = document.querySelectorAll('[data-filter]');
const sizeSelect = document.getElementById('size-filter');

function filterProducts() {
  const activeCategory = document.querySelector('[data-filter].active')?.dataset.filter || 'all';
  const activeSize = sizeSelect.value;

  products.forEach(product => {
    const matchesCategory = activeCategory === 'all' || product.dataset.category === activeCategory;
    const matchesSize = activeSize === 'all' || product.dataset.size === activeSize;

    if (matchesCategory && matchesSize) {
      product.style.display = 'block';
    } else {
      product.style.display = 'none';
    }
  });
}

categoryButtons.forEach(button => {
  button.addEventListener('click', () => {
    categoryButtons.forEach(btn => btn.classList.remove('active'));
    button.classList.add('active');
    filterProducts();
  });
});

sizeSelect.addEventListener('change', filterProducts);

// Set initial active state
document.querySelector('[data-filter="all"]').classList.add('active');
filterProducts();
Enter fullscreen mode Exit fullscreen mode

This approach keeps your page fast, works offline if cached, and makes your Frishay women’s jeans collection feel dynamic. You can extend it easily—add price ranges, color filters, or even sort by popularity. The best part? No backend changes needed.

Give your users control over what they see, and they’ll stay longer, explore more, and actually find those perfect jeans.

Top comments (2)

Collapse
 
rock-randy profile image
Rock

This is a really interesting take! I've been experimenting with a similar approach in my own projects, and I found that combining it with a simple caching layer made a huge difference in performance. Have you considered that?

Collapse
 
rock-randy profile image
Rock

Your point about the learning curve really resonates with me. I remember struggling with this exact concept for weeks before it finally clicked, and your explanation would have saved me so much time. Thanks for sharing!