Search UX & Autocomplete
Designing search that actually works — from autocomplete architecture and keyboard interactions to recovery paths, accessibility, and behavioral instrumentation.
10 min read
Good autocomplete filters as you type, highlights the match, supports full keyboard control, and degrades gracefully when there are no results.
The full lesson
Search is the highest-intent interaction in most digital products. When a user opens a search box, they have a goal. Every friction point between that goal and a result is a failure the product created.
Yet search UX is consistently underdesigned. The input field gets polish, the results page becomes an afterthought, and autocomplete gets bolted on as a nice-to-have. This lesson covers the full picture — from the first keystroke to recovering from zero results — with enough detail to actually ship something that works.
The Search Box: Visibility and Affordance
The single biggest search UX mistake is hiding the search input. An icon that expands into a field on click consistently reduces search engagement. Users either don’t see it or don’t bother with it.
On desktop, expose the input field persistently in the global header. On mobile, a persistent search bar at the top of the screen (the standard Android and iOS pattern) outperforms a corner icon every time.
Size and placeholder text both matter more than most designers expect. A 200 px input signals “short queries only.” Sizing the field to at least 400 px on desktop communicates that the system can handle real queries.
Placeholder text should describe what users can search for — “Search products, brands, and categories” sets scope far better than just “Search.” Never use placeholder text as a label substitute. Pair it with a persistent visible label or an aria-label attribute so the field’s purpose is clear even after the user clicks into it.
Autocomplete Architecture
Autocomplete does two distinct jobs that implementations often mix together:
- Query suggestion — predicting what the user is trying to search for
- Entity surfacing — showing actual matching items directly in the dropdown
These serve different user intents. The design must make the distinction visible.
Query Suggestions vs. Direct Matches
Query suggestions show completions of the user’s partial query. They help users learn vocabulary and skip long typing. Direct entity matches show specific results from your content.
Mix both in the same dropdown, but separate them visually. A section heading, a distinct icon, or different typography is enough.
| Group | Example | Icon cue |
|---|---|---|
| Suggested query | ”running shoes women” | Magnifying glass |
| Category match | ”Shoes > Running” | Folder or tag |
| Product match | ”Nike Air Zoom Pegasus 41” | Product thumbnail |
| Recent search | ”trail running shoes” | Clock |
Start showing suggestions after two or three characters. Fewer than two produces too many irrelevant completions. Waiting for four or five adds unnecessary typing load. Debounce the API call by 150–250 ms to avoid firing a request on every single keystroke.
Keyboard Interaction Requirements
Autocomplete is one of the most keyboard-intensive components in any product. WCAG 2.2 requires full keyboard operability. The ARIA Authoring Practices Guide (APG) defines the combobox pattern — deviating from it without a deliberate replacement is a hard accessibility failure.
Required keyboard behaviors:
- Arrow Down — move focus into the suggestion list
- Arrow Up — move back toward the input, or wrap to the bottom of the list
- Enter — activate the focused suggestion (populate the input or navigate to the result)
- Escape — dismiss the dropdown and return focus to the input
- Tab — dismiss the dropdown and move focus to the next interactive element (do not select the highlighted suggestion on Tab — this breaks screen reader workflows and violates user expectations)
When a suggestion is highlighted via keyboard, the input value should update visually so the user can see what they’ll get. But the original query should be restorable by pressing Escape.
The correct ARIA approach here is aria-activedescendant. This keeps the visual highlight moving while DOM focus stays on the input. Avoid the variant where DOM focus moves into the listbox — it creates more focus-management complexity without benefit.
Announcing to Screen Readers
The dropdown must be announced without requiring the user to leave the input. Use an aria-live="polite" region (outside the dropdown element) to announce how many suggestions are available when the list opens or updates — for example, “5 suggestions available.”
Three attributes are required on the input element to meet WCAG 4.1.2:
role="combobox"aria-controlspointing to the listbox elementaria-expanded="true"or"false"depending on dropdown state
Do
Don't
Inline Highlighting and Ranking
In the autocomplete list, highlight the part of each suggestion that matches what the user typed. The convention is to bold or color-differentiate either the typed portion or the matched portion. Highlighting the match (what the user typed) is slightly more scannable for long suggestions. The goal is to help the eye jump to the differentiating part of each item fast.
Ranking autocomplete results matters just as much as ranking search results. Surface results in this order:
- Exact prefix matches first (“cam” should show “cameras” before “webcam”)
- High-popularity or high-purchase-intent items within entity matches
- Personalized recent searches for logged-in users, clearly labeled
Recent searches provide high-value, low-effort completions. Show them before fresh suggestions when the typed prefix matches. Label them clearly (“Your recent searches”) and include a per-item dismiss action so users can manage their own history.
The Search Results Page
The results page carries most of the UX weight and is most often underdesigned. At minimum it must show:
- The query that ran (or the corrected query if spell-correction was applied)
- The total result count
- Sort controls when relevance ordering alone isn’t enough
- Applied filter chips if filtering is available (covered in detail in the Filtering and Sorting lesson)
- The result list or grid
Result Cards: Show Decision-Making Attributes
Each result card must contain enough information for the user to judge relevance without clicking. The specific attributes depend on domain, but the principle is constant: show the fields the user uses to decide, not just a title.
| Domain | Minimum card attributes |
|---|---|
| E-commerce | Image, product name, price, rating, availability |
| Job board | Title, company, location, salary range, date posted |
| Knowledge base | Title, excerpt with matched terms highlighted, product/version, content type |
| People directory | Name, role, team, avatar, contact action |
Highlight query terms in the excerpt or title using a mark element. Visually, this confirms relevance. Screen readers announce it as highlighted. Don’t highlight so aggressively that the surrounding context disappears.
Sort Controls
Default sort should be relevance for keyword searches and a sensible domain default for browsing (most recent or most popular). Expose alternative sorts — Newest, Price low–high, Highest rated — as a dropdown or segmented control.
On mobile, sort and filter often share a bottom-sheet trigger. Keep them as separate controls inside the sheet so users can apply them independently.
Zero Results: Recovery Is Non-Negotiable
A zero-results page is a product failure, not an edge case. Every zero-results event is a user who wanted something and didn’t get it. Recovery must be designed explicitly. “No results found” with nothing else is never acceptable.
Recovery strategies, in priority order:
- Spell-correct silently — if confidence is high, run the corrected query and show results with a note: “Showing results for ‘running shoes’. Search instead for ‘rnning shoes’.”
- Suggest the corrected query — if confidence is lower, show “Did you mean ‘running shoes’?” without automatically redirecting.
- Relax constraints — if the user has active filters, show “No results match all your filters” with a one-click “Clear filters and search again” action.
- Show related or popular content — surface items from the closest category or the most popular items site-wide with a “You might also like” framing.
- Offer browse entry points — give the user a way to shift from searching to exploring: category links, trending topics, or a curated collection.
Loading States: Skeleton Over Spinner
When a search request is in flight, the loading state sets expectations. The old default — a generic spinner that blocks the whole page — conveys nothing about what’s coming and creates maximum uncertainty.
Modern practice for search result loading:
- Show skeleton screens that approximate the layout of result cards: a gray rectangle where the image will be, two gray bars where the title and excerpt go. This sets expectations about result count and structure, and makes the page feel faster because the layout is already in place.
- For autocomplete dropdown suggestions, a 150–250 ms debounce typically means results arrive before the user notices any wait. Don’t show a spinner inside the dropdown for this latency — just keep the previous state visible until the new results arrive.
- For longer server-side queries or large datasets, show a progress indicator that communicates something is happening. A thin progress bar at the top of the results area is far less disruptive than a full-page spinner.
The guiding principle: the loading state should look as close to the loaded state as possible.
Accessibility: WCAG 2.2 Baseline
WCAG 2.2 AA is the legal baseline in most jurisdictions. Beyond the combobox pattern, search has a few specific requirements:
- Focus not obscured (SC 2.4.11, AA) — if the search input or a suggestion item is focused, it must not be hidden by a sticky header or overlay. WCAG 2.2 added this criterion specifically to address this pattern.
- Target size (SC 2.5.8, AA) — each suggestion item in the autocomplete dropdown must have an interactive hit area of at least 24x24 CSS pixels. Most implementations using 8 px top and bottom padding at 1rem font size pass. Leaner designs with 4 px padding often fail.
- Accessible name — the search input must have an accessible name via a visible
labelelement oraria-label. Placeholder text alone does not count. - Live region for result updates — when the result count changes (new search, filter applied), announce the new count via
aria-live="polite". Without this, screen reader users have no indication the page changed.
One outdated habit to eliminate: using tabindex hacks to manage focus inside the dropdown. The ARIA combobox pattern handles focus semantically through aria-activedescendant. DOM manipulation is unnecessary and creates fragile keyboard behavior.
Scoped Search and Search Within a Context
Not all search is global. Documentation sites, admin dashboards, and content management systems often need scoped search — searching within a section, a date range, a project, or a user’s own content vs. everyone’s content.
Two UI approaches work well:
Scope selector before the input — a dropdown or segmented control to the left of the search field lets users choose the scope before typing. This works well when scopes are few (2–4) and meaningfully different. Default to the most useful scope for most queries; “All” is often the right choice.
Scope as a post-query filter — after results appear, offer scope switching as a tab row or filter chip group above the results. This matches how users actually search: they type first, then narrow. Google’s “All / Images / News / Videos” tabs are the canonical example.
The second approach typically performs better because it lets users see their results before committing to a scope.
Behavioral Instrumentation
Designing a great search experience requires data, not opinion. At minimum, instrument these metrics:
| Metric | What it reveals |
|---|---|
| Query-to-click rate | Are results relevant? A low rate signals a ranking or result card problem. |
| Zero-results rate | Vocabulary gaps, missing content, or index failures |
| Search abandonment rate | Users who searched but never clicked any result |
| Autocomplete acceptance rate | Are suggestions useful? A low rate signals a taxonomy or ranking problem. |
| Reformulation rate | Users who searched again immediately — the first result set failed them |
| Time-to-click | How long users scan before clicking — a proxy for result list clarity |
Review zero-results queries and high-reformulation queries weekly. Feed vocabulary patterns back into your synonym dictionary and content model. Use task-completion rates from usability testing to validate what the quantitative data shows. Behavioral data tells you what is happening. Qualitative testing tells you why.