webdevpuneet.com

Address Autocomplete — Search-As-You-Type HTML CSS JS

Address Autocomplete · Forms · Plain HTML, CSS & JS · Live preview

CategoryForms

Copy & paste

Source Code

<div class="aac-wrap">
  <label class="aac-label" for="aacInput">Shipping address</label>
  <div class="aac-field">
    <svg class="aac-pin" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 1 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
    <input type="text" id="aacInput" placeholder="Start typing a street, city, or zip…" autocomplete="off">
    <button type="button" class="aac-clear" id="aacClear" hidden aria-label="Clear address">✕</button>
  </div>
  <ul class="aac-list" id="aacList" hidden></ul>
  <div class="aac-selected" id="aacSelected" hidden>
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><polyline points="20 6 9 17 4 12"/></svg>
    <span id="aacSelectedText"></span>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Debounced search-as-you-type
A 220ms setTimeout debounce avoids filtering (or fetching) on every single keystroke.
Match highlighting
The matched substring in each suggestion is wrapped in a styled <mark> so users see why it matched.
Full keyboard navigation
ArrowUp/Down, Enter, and Escape behave like a native combobox, with scrollIntoView keeping the highlighted item visible.
No-results state
An empty-state message shows the typed query when nothing matches, instead of a blank dropdown.
Selection confirmation chip
A green checkmark chip confirms the chosen address and hides automatically if the query is edited afterward.
Clear button
A ✕ button resets the input, hides the confirmation, and returns focus to the field.
Outside-click dismissal
Clicking anywhere outside the widget closes the suggestion list, the same pattern used by this library's dropdowns and popovers.
Animation-safe dropdown
Opacity and transform-only transitions keep the suggestion list smooth after every framework export.

About this UI Snippet

Address Autocomplete — Debounced Search, Highlighted Matches & Keyboard Navigation

Screenshot of the Address Autocomplete snippet rendered live

Address autocomplete is one of the highest-value form upgrades you can make: typing a full street address by hand is slow and error-prone, while a filtered suggestion list lets users confirm an address in two keystrokes. This snippet builds the complete pattern — without a paid geocoding API — over a static address list, ready to swap for a real provider.

Debounced filtering

Every keystroke clears a pending setTimeout and schedules a new one 220ms out, so the filter only runs once typing pauses rather than on every single character. This is the standard debounce pattern for search-as-you-type: it keeps the UI responsive while avoiding wasted filter passes (or, with a real API, wasted network requests) on every keystroke.

Substring highlighting

highlight() finds the query's position in each candidate's text with indexOf and wraps the matching slice in a <mark> tag, styled here as a colored, bold span rather than the default yellow highlight. This lets users see *why* each suggestion matched, which builds trust in the list faster than an unhighlighted result.

Full keyboard navigation

Arrow Down/Up move an activeIndex through the visible <li> items, toggling an .active class and calling scrollIntoView({ block: 'nearest' }) so the highlighted item never leaves the dropdown's visible area on a long list. Enter selects the active item (or does nothing if none is highlighted, avoiding an accidental selection), and Escape closes the dropdown without selecting — mirroring native <select> and combobox behavior so keyboard users get an experience they already know.

Selection state and confirmation

Selecting an address (by click or Enter) fills the input with the address's main line, reveals a green confirmation chip showing the full address, and shows a clear ("✕") button. Typing again after a selection hides the confirmation chip immediately, so the UI never shows a stale "confirmed" state next to an edited query.

Animation and dismissal

The dropdown fades and slides in with opacity/transform only (never height), and closes the same way before being hidden via hidden after the transition — keeping it crash-safe across every export target. A document-level click listener closes the list when you click anywhere outside the .aac-wrap container, the same outside-click pattern used by dropdown menus and popovers throughout this library.

Accessibility and a real production geocoder

This demo filters a small static array client-side, which is enough to show the interaction pattern but not enough for real addresses worldwide. A production build swaps the array filter for a debounced fetch to a geocoding provider — Google Places, Mapbox, or Loqate all expose an autocomplete endpoint that takes a partial query and returns ranked suggestions — while keeping the exact same debounce timing, highlight rendering, and keyboard handling described above. For accessibility, add role="combobox" to the input, role="listbox" to the suggestion list, and aria-activedescendant pointing at the currently highlighted option's id, so screen reader users get the same "which suggestion is focused" feedback that sighted keyboard users already see via the .active class.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSAn address input with a pin icon appears. Type at least one character to trigger suggestions.
  2. 2
    Watch the debounced filterAfter a short pause in typing, a dropdown shows up to 6 matches with the typed text highlighted in each one.
  3. 3
    Navigate with the keyboardPress ArrowDown/ArrowUp to highlight a suggestion, Enter to select it, or Escape to dismiss the list.
  4. 4
    Select an addressClick a suggestion or press Enter — the input fills in and a green confirmation chip shows the full address.
  5. 5
    Clear and start overClick the ✕ button to clear the input, hide the confirmation, and refocus the field.
  6. 6
    Swap in a real geocoding APIReplace the ADDRESSES array filter with a fetch to a provider (Google Places, Mapbox, Loqate) inside the debounce timeout, keeping the same render(matches, query) call.

Real-world uses

Common Use Cases

Checkout and shipping forms
Speed up address entry at checkout — pair with a country selector for the country field.
Sign-up and profile forms
Autocomplete home or billing addresses during onboarding instead of five separate manual fields.
Store and service locators
Let users type a starting address before searching nearby locations on a map.
Real-estate and rental search
A property search bar where typing a neighborhood, street, or zip filters listings live.
Delivery and logistics apps
Confirm a precise drop-off address with the same highlighted-match, keyboard-friendly pattern.
Learning combobox patterns
A practical reference for debouncing, ARIA-free keyboard navigation, and outside-click dismissal you can reuse in any autocomplete input.
Related: Address Validation Form
See the Address Validation Form for a related forms pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Replace the ADDRESSES.filter() call inside the debounce timeout with a fetch to your provider's autocomplete endpoint, map its response into { main, sub } objects, and pass them to the existing render(matches, query) function — the highlighting, keyboard navigation, and selection logic all stay the same.

Add role="combobox" and aria-expanded to the input, role="listbox" to the <ul>, role="option" plus aria-selected to each <li>, and an aria-activedescendant on the input pointing at the active item's id — update these alongside the existing activeIndex logic.

Animating height or using display toggles directly causes dropdowns to snap instead of glide once converted to a framework's utility classes. Sticking to opacity and transform (translateY) guarantees a smooth open/close in every export target, including Tailwind.

Filter the ADDRESSES array (or your API request) by a country/region field before applying the text match — add a country dropdown above the input and pass its value into the filter condition.

In React, track the query, matches, and activeIndex in useState and debounce with a useRef timer inside useEffect; in Vue, use ref()/watch(); in Angular, use a component method with a debounce via RxJS. The highlight, keyboard handling, and outside-click logic port directly.