01 — Foundation

Filtering helps users find what matters

Good filtering reduces noise. Bad filtering hides results and erodes trust.

Filtering and sorting let users narrow large datasets to what they need. When controls are unclear, state is invisible, or results jump unpredictably, people assume the product is broken — even when the data is fine.

02 — Filters

Filters users can understand

Expose what is active, how many results match, and how to reset.

  • use real form controls — checkboxes, radios, selects, search fields — not mystery toggles
  • show active filters as removable chips or a summary line
  • show result counts and loading state while data updates
  • provide a clear reset — “Clear all filters” beats hunting individual controls
<form method="get" action="/products/">
    <label for="category">Category</label>
    <select id="category" name="category">
        <option value="">All categories</option>
        <option value="books">Books</option>
    </select>
    <button type="submit">Apply filters</button>
</form>

03 — Sort

Sorting without surprises

Sort direction and active column should be obvious to everyone.

  • label the sort control — “Sort by”, not an icon-only mystery menu
  • indicate direction and keep keyboard access without layout jumps
  • preserve sort in the URL when sharing or refreshing should keep context
  • default to a sensible order; document when server-side sort is required

04 — States

Empty, loading, and errors

No results is information — treat it like an empty state, not a failure.

  • meaningful empty copy — “No invoices for March 2026”, not “No data”
  • distinguish zero results from loading and from server errors
  • calm loading for large datasets; avoid skeleton theatre for tiny lists

Too vague

'No data'

Clearer

'No products match these filters. Try removing “In stock only” or browse all categories.'

05 — Review

Before you approve

A short checklist for filtering and sorting in code review.

  • active filters and sort are visible, resettable, and keyboard accessible
  • results update predictably; empty and error states are specific
  • URL or form state supports refresh and share where that matters