Pure TailwindMIT licensed

Tailwind Search Input With Clear

A pill search field with a leading magnifier and a trailing clear button that only exists when there is something to clear. type="reset" does the clearing; has-[input:placeholder-shown]: does the hiding.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<div class="tif-08 grid min-h-svh w-full place-items-center bg-tif08-bg px-6 py-14 font-tif08-sans" aria-label="Search input with clear demo">
  <form role="search" class="group relative flex w-full max-w-80 items-center gap-1 rounded-full border border-white/10 bg-tif08-field pr-1.5 pl-10 transition-[border-color,box-shadow] duration-200 focus-within:border-tif08-acc focus-within:ring-3 focus-within:ring-tif08-acc/18">
    <span class="pointer-events-none absolute left-3.5 grid place-items-center text-tif08-mut transition-colors group-focus-within:text-tif08-acc" aria-hidden="true">
      <svg viewBox="0 0 16 16" width="14" height="14"><path fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" d="M11 11l3 3M7 12a5 5 0 1 1 0-10 5 5 0 0 1 0 10z"/></svg>
    </span>
    <input type="search" name="q" placeholder="Search projects, people, files…" aria-label="Search"
      class="min-w-0 flex-1 border-0 bg-transparent py-2.5 text-sm text-tif08-ink outline-none placeholder:text-tif08-mut [&::-webkit-search-cancel-button]:hidden">
    <button type="reset" aria-label="Clear search"
      class="grid size-11 shrink-0 cursor-pointer place-items-center rounded-full border-0 bg-transparent text-tif08-mut transition-[opacity,background-color,color] duration-150 hover:bg-white/12 hover:text-tif08-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tif08-acc group-has-[input:placeholder-shown]:pointer-events-none group-has-[input:placeholder-shown]:opacity-0">
      <svg viewBox="0 0 12 12" width="10" height="10" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" d="M2 2l8 8M10 2l-8 8"/></svg>
    </button>
  </form>
</div>
@import "tailwindcss";

@theme {
  --color-tif08-bg: #12121a;
  --color-tif08-bg: oklch(0.19 0.015 285);
  --color-tif08-field: #1a1a22;
  --color-tif08-field: oklch(0.23 0.015 285);
  --color-tif08-ink: #f0eeff;
  --color-tif08-ink: oklch(0.95 0.02 290);
  --color-tif08-mut: #b8b6d4;
  --color-tif08-mut: oklch(0.77 0.03 290);
  --color-tif08-acc: #60a5fa;
  --color-tif08-acc: oklch(0.73 0.14 255);
  --font-tif08-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tif-08 {
  width: 100%;
}

.tif-08 ::selection {
  background: var(--color-tif08-acc);
  color: #12121a;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tif08-bg: #12121a;
  --color-tif08-bg: oklch(0.19 0.015 285);
  --color-tif08-field: #1a1a22;
  --color-tif08-field: oklch(0.23 0.015 285);
  --color-tif08-ink: #f0eeff;
  --color-tif08-ink: oklch(0.95 0.02 290);
  --color-tif08-mut: #b8b6d4;
  --color-tif08-mut: oklch(0.77 0.03 290);
  --color-tif08-acc: #60a5fa;
  --color-tif08-acc: oklch(0.73 0.14 255);
  --font-tif08-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tif-08 {
  width: 100%;
}

.tif-08 ::selection {
  background: var(--color-tif08-acc);
  color: #12121a;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • The clear button grew from 22px to size-11 (44px) with a transparent background — same visual weight, a tap target that passes WCAG 2.5.5.
  • :has(input[value=&quot;&quot;]) is dropped: it never worked, because the attribute does not track what the user typed. :placeholder-shown does.
  • The ::-webkit-search-cancel-button reset stays a bracket selector — Tailwind has no variant for it and should not invent one.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Search Input With Clear
Source: https://codefronts.com/components/tailwind-css-input-fields/tailwind-search-input-with-clear/

A pill search field with a leading magnifier and a trailing clear button that only exists when there is something to clear. type="reset" does the clearing; has-[input:placeholder-shown]: does the hiding.
## HTML
```html
<div class="tif-08 grid min-h-svh w-full place-items-center bg-tif08-bg px-6 py-14 font-tif08-sans" aria-label="Search input with clear demo">
  <form role="search" class="group relative flex w-full max-w-80 items-center gap-1 rounded-full border border-white/10 bg-tif08-field pr-1.5 pl-10 transition-[border-color,box-shadow] duration-200 focus-within:border-tif08-acc focus-within:ring-3 focus-within:ring-tif08-acc/18">
    <span class="pointer-events-none absolute left-3.5 grid place-items-center text-tif08-mut transition-colors group-focus-within:text-tif08-acc" aria-hidden="true">
      <svg viewBox="0 0 16 16" width="14" height="14"><path fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" d="M11 11l3 3M7 12a5 5 0 1 1 0-10 5 5 0 0 1 0 10z"/></svg>
    </span>
    <input type="search" name="q" placeholder="Search projects, people, files…" aria-label="Search"
      class="min-w-0 flex-1 border-0 bg-transparent py-2.5 text-sm text-tif08-ink outline-none placeholder:text-tif08-mut [&::-webkit-search-cancel-button]:hidden">
    <button type="reset" aria-label="Clear search"
      class="grid size-11 shrink-0 cursor-pointer place-items-center rounded-full border-0 bg-transparent text-tif08-mut transition-[opacity,background-color,color] duration-150 hover:bg-white/12 hover:text-tif08-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tif08-acc group-has-[input:placeholder-shown]:pointer-events-none group-has-[input:placeholder-shown]:opacity-0">
      <svg viewBox="0 0 12 12" width="10" height="10" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" d="M2 2l8 8M10 2l-8 8"/></svg>
    </button>
  </form>
</div>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tif08-bg: #12121a;
  --color-tif08-bg: oklch(0.19 0.015 285);
  --color-tif08-field: #1a1a22;
  --color-tif08-field: oklch(0.23 0.015 285);
  --color-tif08-ink: #f0eeff;
  --color-tif08-ink: oklch(0.95 0.02 290);
  --color-tif08-mut: #b8b6d4;
  --color-tif08-mut: oklch(0.77 0.03 290);
  --color-tif08-acc: #60a5fa;
  --color-tif08-acc: oklch(0.73 0.14 255);
  --font-tif08-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tif-08 {
  width: 100%;
}

.tif-08 ::selection {
  background: var(--color-tif08-acc);
  color: #12121a;
}
```

How this works

Empty is a state the form can read. The whole toggle is one variant pair on the button, with no script and no class swapping:

class="transition-opacity
  group-has-[input:placeholder-shown]:pointer-events-none
  group-has-[input:placeholder-shown]:opacity-0"

Reset needs its own form. type="reset" clears every field in the enclosing form, which is exactly right when the search field is the form — as here — and exactly wrong when it is one field among many.

Make it yours

  • Icons: both SVGs are stroke=&quot;currentColor&quot;, so they inherit from the utilities around them.
  • Shape: rounded-full on the shell. rounded-xl gives a boxier search bar.
  • Halo: focus-within:ring-3 focus-within:ring-tif08-acc/18.
  • Reveal: duration-150 on the clear button's opacity transition.

Gotchas — read before shipping

  • The placeholder must be non-empty or :placeholder-shown never flips and the button never appears.
  • type=&quot;reset&quot; resets the whole form — wrap the field in its own <form>, as here, or use a click handler.
  • A hidden-but-focusable button is a focus-order bug: pointer-events-none plus opacity-0 is the minimum, and hidden would be better if you can accept no transition.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

:has() is Baseline as of Firefox 121; without it the clear button is always visible and still works.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…