Forms✨ Premium

Search Expand

A round pill with a magnifier that stretches into a 280 px search field on click or Tab, and only closes again if it was left empty.

CSSFocusTransform

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Forms has 20 effects, including 2 free. Explore the category →

3 usage examples

Header magnifier on a cooking blog — Pistelune — Search Expand example 1

① Header magnifier on a cooking blog — Pistelune

WhenTop right, beside the Recipes, Seasons and Desserts sections: clicking the magnifier unfolds the field to the left, over the menu, and three recipes appear under it from the first letters.
WhyThe header has no room for a permanent 280 px field; the pill takes only 62 px while nobody is searching, and the menu stays readable.
SettingsRoot positioned absolutely at the right of the header with justify-content: flex-end, so it opens leftwards. The scene hides the menu with :focus-within and :has(.sxp-input:not(:placeholder-shown)). aria-label="Search for a recipe".
Filter for the contacts column of a messaging app — Caldrune — Search Expand example 2

② Filter for the contacts column of a messaging app — Caldrune

WhenThe "/" key focuses the filter from anywhere; the pill stretches across the column and the list keeps only the contacts whose name contains the typed letters.
WhyA 236 px column has no room for a title, a field and a list; the folded pill lets the list start higher and opens when it is time to filter.
Settings--sxp-width: 208px, aria-keyshortcuts="/", name="contact". The shortcut and the list filtering are scene code, hooked to the input event.
"+" button of a shared shopping list on mobile — Panimbre — Search Expand example 3

③ "+" button of a shared shopping list on mobile — Panimbre

WhenUnder the list, a pill marked "+": a tap unfolds it into an "Add an item" field, Enter adds the line and empties the field, which stays open for the next item; leave it empty and it becomes a pill again.
WhyOn a phone screen the pill steals no room from the list, and the "closed only when empty" rule suits an add field: nothing disappears until the item is confirmed.
SettingsMagnifier replaced by a "+" SVG in .sxp-icon, --sxp-width: 226px, aria-label="Add an item", enterkeyhint="done", autocomplete="off".

How it works

The .sxp-input field (type="search") is the pill itself: width: 50px, 50px corners and a 44 px left padding that leaves room for the magnifier. With that padding, the closed pill is actually 62 px wide. The .sxp-icon magnifier is an SVG laid on top, 14 px from the edge, ignoring clicks (pointer-events: none): clicking it is clicking the field.

Two states open the pill: .sxp-input:focus, and .sxp-input:not(:placeholder-shown), meaning "the field holds text". Either way the width goes to --sxp-width (280 px by default), the frame turns indigo #6366f1 and the fill takes a light tint, over 0.5 s on a cubic-bezier(.4, 0, .2, 1) curve. The magnifier goes from grey #8b8b93 to indigo while the field has focus.

When the visitor leaves the field, only the text rule can keep it open: empty, it turns back into a pill; filled, it stays unfolded and shows what was typed. Not a line of JavaScript is needed, and each copy on the page behaves independently. The .fx-0287-root root is only a 300 px demo background.

Accessibility

  • Field name: with no visible label (the magnifier stands in for it), the field carries aria-label="Search"; screen readers announce "Search, search field". The magnifier is hidden with aria-hidden="true".
  • Submitting: name="q" is supplied. Inside a <form role="search">, Enter sends the query; on phones, type="search" shows the keyboard's Search key.
  • Keyboard and touch: the pill is the field itself, so Tab opens it and so does a tap, with no element in between.
  • Reduced motion: under prefers-reduced-motion: reduce, the pill opens and closes without a transition.
  • Touch target: closed, the pill is about 62 × 50 px, above the recommended 44 px.

Browser compatibility

Relies on :placeholder-shown (Chrome 47, Firefox 51, Safari 9), one CSS variable (Chrome 49, Firefox 31, Safari 9.1) and appearance: none, also declared with the -webkit- prefix to clear Safari's native search field styling. Measured in Chromium, Firefox and WebKit: two pills in one form, the second opened and filled while the first stays closed, Tab, touch, reduced motion. The captures are played by the scene script (simulated focus, typing and "/" shortcut), which is not part of the code you buy.

Chrome 49+✓ Full (measured)
Firefox 51+✓ Full (measured)
Safari 9.1+✓ Full (WebKit engine measured)
Edge 79+✓ Full (Chromium engine)
Mobile iOS 9.3+✓ Full
Android Chrome 49+✓ Full (Chromium engine)

Without :placeholder-shown, the pill closes even when filled and hides the text; it still opens on focus. Without appearance: none, an old Safari may keep the corners and padding of its native search field.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0287-root">
  <div class="sxp-group">
    <input class="sxp-input" type="search" name="q" aria-label="Search" placeholder="Search...">
    <span class="sxp-icon" aria-hidden="true">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" focusable="false">
        <circle cx="11" cy="11" r="8"></circle>
        <path d="M21 21l-4.35-4.35"></path>
      </svg>
    </span>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Open width (CSS — --sxp-width) 280 px A fixed length (px, rem). For a percentage, first give .sxp-group a width, otherwise the pill has no reference. max-width: 100% prevents overflow on mobile.
Opening direction (CSS — parent container) centred in the root In a header, align the parent right (justify-content: flex-end) so the field grows leftwards, or left so it pushes rightwards.
Opening duration (CSS — transition of .sxp-input) 0.5 s The magnifier colour changes in 0.3 s. Above 0.6 s, the first typed letters arrive before the opening ends.
Colours (CSS — border-color, background, color) indigo #6366f1, magnifier #8b8b93 Values written in the :focus and .sxp-icon rules; on a light background, make the field text dark too.
Icon (HTML — content of .sxp-icon) 20 × 20 SVG magnifier Any 20 px SVG, for instance a "+" for an add field. Keep aria-hidden="true" and update aria-label.
Hint text (HTML — placeholder) Search... Required: it is what tells whether the field is empty. To show nothing, use a single space.

FAQ

Because it holds text. The pill only closes when empty, so the typed search stays visible. Empty the field (or call input.value = '') and it folds on the next exit.
Wrap the group in a <form role="search" action="/search">: Enter sends ?q=… with no extra button, since the field is already named q.
The :placeholder-shown selector already knows whether the field is empty, for each field separately and without any id. Several searches on the same page therefore open and close on their own, and the effect works even when scripts are blocked.