sodcalculator

10 Tech How-To

Vanilla JS Search & Filters for Marketplaces

Guide 10-32053 · Updated · Step by step

This guide shows you how to add fast, user-friendly search and filtering to a marketplace using only vanilla JavaScript. You’ll learn to build a search bar that matches product names and descriptions, plus category, price, and rating filters that update results instantly. No libraries or frameworks are needed—just a modern browser and a basic understanding of HTML, CSS, and JavaScript.

What You’ll Need

  • A basic HTML page with a list of products (each product in a container with data attributes for category, price, and rating).
  • Basic knowledge of JavaScript (functions, event listeners, array methods like filter and includes).
  • A code editor and a browser (Chrome, Firefox, Edge, etc.) to test your code.

Step-by-Step

  1. Set up your HTML structure.

    Create a search input, filter controls (e.g., a category dropdown, price range inputs, and a rating select), and a container for your products. Each product should be a div with a class like product, and store its category, price, and rating as data attributes. For example:

    <div class="product" data-category="electronics" data-price="299" data-rating="4.5">
      <h3>Wireless Headphones</h3>
      <p>High-quality sound with noise cancellation.</p>
    </div>
  2. Write the filter function.

    Create a function, say applyFilters(), that reads the current values of all filters (search text, category, price min/max, rating) and returns a filtered list of products. Use Array.prototype.filter() to check each product against the criteria. For text search, use toLowerCase() and includes() to make it case-insensitive.

  3. Handle the search input.

    Add an event listener to the search input for the input event. This fires on every keystroke, so the results update live. Call applyFilters() inside the listener.

  4. Handle filter changes.

    Add change event listeners to the dropdowns, range inputs, and checkboxes. These also call applyFilters(). Use change for selects and checkboxes, and input for range sliders if you want live updates.

  5. Show or hide products.

    In applyFilters(), loop through all product elements. For each product, check if it passes all filter conditions. If it does, set product.style.display = 'block'; otherwise, set it to 'none'. Alternatively, you can rebuild the list with innerHTML, but hiding/showing is simpler and preserves event listeners.

  6. Add a “no results” message.

    After filtering, count how many products are visible. If zero, show a message like “No products match your criteria.” Hide it otherwise. This improves user experience.

  7. Test thoroughly.

    Try combining filters: search for “headphones” while selecting “electronics” and a price range. Make sure the results update correctly. Also test edge cases like empty search or no filters selected (should show all products).

Common Mistakes

  • Forgetting to parse data attributes: Data attributes are strings. Use parseFloat() or parseInt() when comparing numeric values like price or rating.
  • Case sensitivity in search: If you don’t use toLowerCase(), searching “Headphones” won’t match “headphones”. Always normalize both the search term and the text being searched.
  • Not updating on every input: Using only change on the search input means the filter only applies when the input loses focus. Use input for live feedback.
  • Mixing up filter() and find(): filter() returns an array of all matches; find() returns only the first match. For a marketplace, you want filter().
  • Overwriting the entire list with innerHTML: If you rebuild the DOM, you lose any event listeners attached to product elements. Instead, hide/show existing elements.

Tips

  • Debounce the search input: For large product lists, add a debounce function to delay the filter until the user stops typing (e.g., 200ms). This prevents performance issues.
  • Use URL parameters for shareable filters: On filter change, update the URL query string (e.g., ?category=electronics&minPrice=100). On page load, read these parameters and apply them. This is a nice touch for users to share filtered views.
  • Sort results: Add a sort dropdown (e.g., price low-to-high, rating high-to-low). Use Array.prototype.sort() on the filtered array before displaying.
  • Accessible labels: Use <label> elements for each filter control so screen readers can announce them. This improves accessibility.
  • Keep the code modular: Separate the filter logic from the DOM manipulation. This makes it easier to test and extend.

Troubleshooting

  • Filters don’t update: Check that your event listeners are attached correctly. Open the browser console (F12) and look for errors. Ensure the elements exist when the script runs (place the script at the end of the <body> or use DOMContentLoaded).
  • Products disappear with no results: This is expected behavior. Make sure your “no results” message is visible and styled properly.
  • Price range not working: Verify that you’re using parseFloat() on both the data attribute and the input value. Also check that the min and max values are not reversed (min should be less than max).
  • Search matches too many or too few: If you’re searching only the title, but users expect description search, include both. If you’re using includes(), it does substring matching, which is usually fine. If you need whole-word matching, use a regex with word boundaries.
  • Performance issues with large lists: If you have hundreds of products, consider using a simple indexing technique or a library like Fuse.js (but that’s not vanilla). For pure vanilla, debouncing and avoiding complex DOM operations help.

Frequently Asked Questions

Can I use this with a framework like React or Vue?

Yes, the logic is similar, but you’d use framework-specific state management and rendering. The vanilla approach here is a good starting point to understand the concepts.

How do I filter by multiple categories at once?

Use checkboxes for categories instead of a dropdown. Store selected categories in an array, and check if the product’s category is in that array.

How do I sort results after filtering?

After filtering, use Array.prototype.sort() on the filtered array. For example, to sort by price ascending: filtered.sort((a, b) => a.price - b.price).

What if my product data is in a JSON file?

Fetch the JSON with fetch(), then generate the product HTML dynamically. The filter logic stays the same, but you’ll rebuild the list on each filter change.

How do I handle pagination with filters?

Apply filters first, then paginate the filtered results. You can use a library like pagination.js, or write a simple one that shows a subset of products per page.

Is it better to hide elements or rebuild the DOM?

Hiding elements is simpler and preserves any event listeners. Rebuilding is faster for very large lists (thousands of items) but requires re-attaching listeners. For most marketplaces, hiding is sufficient.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →