Search
Last updated:
Practical patterns for labelled search fields, results states, and enhancements that degrade gracefully.
01 — Foundation
Search should feel predictable
Users expect to type, submit, see results, and recover when nothing matches.
Search is one of the fastest ways to lose trust. Slow feedback, mystery placeholders, results that jump, and errors buried in toasts make people repeat queries or leave. This pattern covers practical search UI — not enterprise search architecture.
02 — Input
The search field itself
Start with a real labelled input before adding instant suggestions.
- visible label or accessible name — placeholder is not a label
-
use
type="search"where appropriate; keep submit explicit when results are server-driven - show what scope is searched — “Search products”, not generic “Search”
- clear button when the field often holds long queries
<form role="search" action="/search/" method="get">
<label for="site-search">Search products</label>
<input id="site-search" name="q" type="search" autocomplete="off" />
<button type="submit">Search</button>
</form> 03 — Results
Results, loading, and no matches
Every state should answer: did it work, and what can I do next?
- show that a search ran — query echoed, result count, or “Showing results for…”
- loading feedback proportional to wait time; avoid flashing empty lists
- empty results with guidance — spelling, filters, broader terms
- errors inline with retry — not only a toast users might miss
04 — Enhancement
Live search and suggestions
Instant results are optional polish — the baseline should work without them.
- debounce requests; cancel in-flight fetches when the query changes
- combobox patterns for suggestions — keyboard, focus, and aria-expanded
- do not trap users in client-only search with no shareable URL when lists matter
- respect reduced motion; avoid animating every keystroke
05 — Review
Before you approve
A short checklist for search UI in code review.
- labelled input, clear submit path, and understandable scope
- loading, empty, and error states are specific and recoverable
- enhancements degrade gracefully without JavaScript