UI/UX Atlas
UI Patterns Intermediate

Search UX & Autocomplete

Designing search that actually works — from autocomplete architecture and keyboard interactions to recovery paths, accessibility, and behavioral instrumentation.

10 min read

Interactive example · Search with autocomplete

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.

GroupExampleIcon 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-controls pointing to the listbox element
  • aria-expanded="true" or "false" depending on dropdown state

Do

Use the ARIA combobox pattern with aria-activedescendant to keep focus on the input while visually highlighting suggestions. Announce suggestion count via an aria-live region. Allow Escape to dismiss without activating anything. Bold or color the matched query terms in each suggestion so users can scan quickly.

Don't

Move DOM focus into the dropdown on keyboard navigation — it breaks the ability to continue typing. Select the highlighted suggestion on Tab — it disrupts natural focus flow. Show query completions and direct entity results in the same unsorted list with no visual distinction between them.

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:

  1. Exact prefix matches first (“cam” should show “cameras” before “webcam”)
  2. High-popularity or high-purchase-intent items within entity matches
  3. 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.

DomainMinimum card attributes
E-commerceImage, product name, price, rating, availability
Job boardTitle, company, location, salary range, date posted
Knowledge baseTitle, excerpt with matched terms highlighted, product/version, content type
People directoryName, 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:

  1. 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’.”
  2. Suggest the corrected query — if confidence is lower, show “Did you mean ‘running shoes’?” without automatically redirecting.
  3. 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.
  4. 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.
  5. 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 label element or aria-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:

MetricWhat it reveals
Query-to-click rateAre results relevant? A low rate signals a ranking or result card problem.
Zero-results rateVocabulary gaps, missing content, or index failures
Search abandonment rateUsers who searched but never clicked any result
Autocomplete acceptance rateAre suggestions useful? A low rate signals a taxonomy or ranking problem.
Reformulation rateUsers who searched again immediately — the first result set failed them
Time-to-clickHow 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.