On this page
Search and filters form one conversation with a collection: find these items, narrow them this way, then explain what remains. A polished search field cannot compensate for hidden constraints or a result count that changes without explanation. Design the controls, selected state and results as one connected interface.
Establish scope and the primary layout
Write down what the search actually matches: product names, descriptions, identifiers, owners or all indexed fields. Search scope should be understandable near the field. Search orders by number or customer gives people a more reliable starting point than a bare magnifying glass and an ambiguous placeholder.
Use the Flexbox playground to explore a toolbar containing a flexible search field, filter controls and a sort menu. Try wrapping and longer labels before choosing fixed widths. Reserve room for the search field rather than allowing secondary actions to squeeze it into an unusable slot.
Choose the layout around collection size and task frequency. A catalog with many stable facets may justify a sidebar. A dashboard with three common constraints may work better with a compact toolbar. Avoid copying a shopping layout into an operational table when users primarily look up exact record identifiers.
Separate finding, narrowing and ordering
Search retrieves matches to a query. Filters constrain the collection by known attributes. Sorting changes order without changing membership. Give these different jobs distinct visual controls so users can predict the effect of each interaction.
Place common filters close to the query, and move infrequent options into an additional panel. A product catalog might expose category and price while keeping material and dimensions behind More filters. A support dashboard might prioritize status, assignee and updated date. The visible set should reflect routine decisions, not every field in the database.
For single-choice values, use a select or radio group according to available space and option count. Use checkboxes for multiple selections where appropriate. State the matching logic when ambiguity matters: selecting Red and Blue normally means either color, while selecting In stock and On sale usually means both conditions.
The Nielsen Norman Group guidance on search visibility supports keeping search recognizable. Do not hide the primary search behind an icon merely to make a desktop toolbar appear cleaner. A persistent label remains useful even when example text is shown inside the field.
Choose when changes become results
Immediate filtering works when updates are fast and choices are independent. The interface should show that a result update is occurring without repeatedly emptying the content area. For typed search, a short debounce can reduce unnecessary requests, but it is a tuning choice rather than a guarantee of good interaction.
Explicit apply works well when users configure several expensive or interdependent criteria. Keep draft values separate from active filters, and label the button Apply filters. Closing the panel should have a defined outcome: either preserve the draft for later or discard it clearly. Do not silently apply a half-completed range.
Decide these behaviors before implementation:
- Does typing search immediately, or require submission?
- Do changes inside the filter panel affect results before Apply?
- Does Clear reset only the query or every active constraint?
- Does changing a filter reset pagination to the beginning?
- What happens to selected rows that are no longer visible?
For a simple submitted search, native controls establish a dependable starting point:
<form role="search" action="/catalog" method="get">
<label for="catalog-query">Search products</label>
<input id="catalog-query" name="q" type="search"
placeholder="Name or product code">
<label for="availability">Availability</label>
<select id="availability" name="availability">
<option value="">Any availability</option>
<option value="in-stock">In stock</option>
</select>
<button type="submit">Search products</button>
</form>The action above is an illustrative application route, not a Stockio destination. MDN's search input reference covers native behavior. Build additional interactions only when the task needs them; a custom combobox brings substantially more behavior than a plain search input.
Make the active state visible and reversible
Show active constraints near the result heading, not only inside a closed panel. Removable chips can summarize discrete values, while a date range is often clearer as one combined item. Give each remove control a specific accessible name, such as Remove status: Open, rather than a repeated unexplained cross.
Distinguish Clear search from Clear all filters. If a global date scope remains active, do not label a partial reset Clear all. Display inherited constraints when they materially affect results, including workspace or permission scope. Otherwise people may assume that missing records do not exist.
Use result counts that explain the state: 24 products matching your filters is clearer than a detached 24. If counts are approximate or still loading, say so. Facet counts must have a defined meaning, particularly whether they reflect the current selection or the results of adding an option.
Preserve query, filters and sort state when someone opens a record and returns. Where appropriate, serialize shareable state into the URL. MDN's URLSearchParams documentation is a practical implementation reference. Avoid placing sensitive search values in shareable URLs without considering history and logging exposure.
Design narrow layouts and imperfect states
On narrow screens, keep the query and a labeled Filters button visible. Include an active-filter count if it helps communicate hidden state. A drawer can hold the controls, but its Apply action must remain reachable without covering the final options. Preserve draft selections if the person briefly leaves the panel to inspect a result.
For result layouts, Grid versus Flexbox for dashboards helps separate toolbar behavior from content structure. Keep sorting near the result list even when filters move into a drawer. Otherwise people may search the filter panel for an ordering control that is no longer visible.
Treat zero results as a recoverable state. Repeat the query, summarize the active constraints and offer targeted next steps: remove the price limit, expand the date range or clear the query. Do not automatically discard filters just to populate the screen. That changes the question without permission.
A failed request is not an empty collection. Preserve the last confirmed results when useful, mark them as not updated, and offer Retry. The guide to asynchronous error states provides useful patterns for separating loading, failure and genuine emptiness. Test rapid changes too: a slow response to an earlier query must not overwrite the newest results.
Key takeaways
- Explain search scope and distinguish retrieval, filtering and sorting.
- Choose immediate updates or explicit application deliberately.
- Keep active constraints visible outside closed panels.
- Preserve useful state across navigation and make resets precise.
- Design zero results, failed requests and narrow layouts together.
Reach designers & developers at work
Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.
Become a sponsor