Skip to content

Expanding Search Bar

Search icon button that expands into a pill-shaped input, shown in a dark navbar and a large hero search, with Escape to close and a demo submit.

Live preview

Open in new tab

Code

An expanding search bar built with CSS and a small vanilla JavaScript file: a round icon button that grows into a pill-shaped search field when clicked. The demo places one collapsed instance in a dark navbar and a large, already open instance in a help-center hero. Use it in headers, toolbars and documentation sites where space is tight.

How it works

Each instance is a form.xs-search with role="search". Inside are a visually hidden label (.xs-sr), the input.xs-input, a .xs-close button and the .xs-btn submit button with the magnifier icon, plus a .xs-status paragraph for messages. The form is a flex row, so when it sits at the end of the .xs-bar it grows to the left.

script.js loops over every .xs-search, adds .xs-ready and keeps aria-expanded and the button label in sync. The collapsed look only applies to .xs-search.xs-ready:not(.is-open): the input and close button shrink to width: 0, fade out and become visibility: hidden, so they cannot be tabbed to. The script listens to submit: if the form is collapsed it adds .is-open and focuses the input instead of submitting. Once open, a non-empty query shows a simulated message in .xs-status. Escape (keydown), the close button and a focusout with an empty field collapse it again. Without JavaScript .xs-ready is never added, so the field stays open and the form submits normally.

Customization

  • --xs-accent on .xs-demo: the lime color of the submit button and the focus ring.
  • --xs-width: the expanded input width, e.g. 20rem; the navbar uses 9.5rem on phones.
  • --xs-size: the diameter of the round .xs-btn and the height of the field.
  • --xs-speed: how fast the field expands and fades.
  • .xs-search--light: a white field with dark text; .xs-search--lg makes a taller, full-width hero search.
  • Add is-open to a .xs-search in the HTML to render it expanded on load, as in the hero.
  • In the submit handler in script.js, replace the setTimeout demo with fetch('/search?q=' + encodeURIComponent(query)) or set a real action and remove preventDefault().

Accessibility

Each form has role="search" and the input has a real label. The submit button announces "Open search" or "Submit search" and exposes aria-expanded and aria-controls, so screen reader users know the field is revealed. Focus moves into the input on open and back to the button on close. Results are announced through .xs-status, which has role="status". Buttons show a 3px focus outline and the open field shows an accent ring via :focus-within. Animations are turned off under prefers-reduced-motion: reduce.

Usage notes

Every .xs-search is independent, so you can place several on one page. Give each input a unique id that matches its label.

Requirements

No dependencies. Pure HTML, CSS and JavaScript.

Expanding Search Bar – Pure CSS search bars component screenshot
Expanding Search Bar · Pure CSS Search Bars

More Search Bars

Search with Autocomplete – Bootstrap 5 search bars preview

Search with Autocomplete

Bootstrap 5 help center search bar with an accessible autocomplete list built from local data, highlighted matches, keyboard navigation and popular search chips.

Command Palette Search – Tailwind CSS search bars preview

Command Palette Search

Dark Tailwind CSS command palette opened with Ctrl+K: live filtering with match highlights, grouped results and full keyboard navigation.