Components
Input group
Icons, text, buttons, menus and spinners inside an input's border, on either side, above or below.
<div class="input-group max-w-sm">
<input class="input" type="search" placeholder="Search…" aria-label="Search" />
<span class="input-group-addon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg></span>
<span class="input-group-addon input-group-addon-inline-end">12 results</span>
</div>
Usage#
- Wrap a
.input,.textareaor.selectin.input-group. The group draws the border and the focus ring; the control drops its own. - Add each addon as a
.input-group-addon. Put addons after the control in the source. CSS places them, so Tab reaches the control first. - States come from the control:
aria-invalid="true"turns the whole group red anddisabledfades it.
Align#
An addon goes at the inline start by default. .input-group-addon-inline-end puts it at the end,
.input-group-addon-block-start above the control and .input-group-addon-block-end below it.
<div class="input-group max-w-sm">
<input class="input" placeholder="Inline start" aria-label="Inline start" />
<span class="input-group-addon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg></span>
</div>
<div class="input-group max-w-sm">
<input class="input" type="password" placeholder="Inline end" aria-label="Password" />
<span class="input-group-addon input-group-addon-inline-end"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg></span>
</div>
<div class="input-group max-w-sm">
<input class="input" id="ig-block-start" placeholder="Block start" />
<label class="input-group-addon input-group-addon-block-start" for="ig-block-start">Full name</label>
</div>
<div class="input-group max-w-sm">
<input class="input" placeholder="Block end" aria-label="Amount" />
<span class="input-group-addon input-group-addon-block-end"><span class="input-group-text">Billed in USD</span></span>
</div>
Icons and text#
Addons hold icons, text or both. .input-group-text styles plain text inside a busier addon.
<div class="input-group max-w-sm">
<input class="input" type="email" placeholder="you@example.com" aria-label="Email" />
<span class="input-group-addon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
</div>
<div class="input-group max-w-sm">
<input class="input" placeholder="example.com" aria-label="Website" />
<span class="input-group-addon">https://</span>
<span class="input-group-addon input-group-addon-inline-end">.com</span>
</div>
<div class="input-group max-w-sm">
<input class="input" type="number" placeholder="0.00" aria-label="Price" />
<span class="input-group-addon">$</span>
<span class="input-group-addon input-group-addon-inline-end">USD</span>
</div>
Buttons#
Buttons inside an addon shrink to fit (24px tall). Use any variant; ghost and secondary sit most naturally.
<div class="input-group max-w-sm">
<input class="input" value="https://htmx-ui.dev/r/3f9a" readonly aria-label="Share link" />
<span class="input-group-addon input-group-addon-inline-end">
<button class="btn btn-ghost btn-icon" aria-label="Copy"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><rect width="14" height="14" x="8" y="8" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button>
</span>
</div>
<div class="input-group max-w-sm">
<input class="input" type="search" placeholder="Search the docs…" aria-label="Search" />
<span class="input-group-addon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg></span>
<span class="input-group-addon input-group-addon-inline-end">
<button class="btn btn-secondary">Search</button>
</span>
</div>
Badges#
<div class="input-group max-w-sm">
<input class="input" placeholder="Add a label…" aria-label="Labels" />
<span class="input-group-addon">
<span class="badge badge-info">bug</span>
<span class="badge badge-secondary">ui</span>
</span>
</div>
Dropdown#
A dropdown in an addon, for picking a unit or scope.
<div class="input-group max-w-sm">
<input class="input" placeholder="Search…" aria-label="Search" />
<span class="input-group-addon input-group-addon-inline-end">
<span class="dropdown" data-dropdown>
<button class="btn btn-ghost" data-dropdown-trigger aria-haspopup="menu" aria-expanded="false">All files <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
<span class="dropdown-menu dropdown-menu-end" role="menu" hidden>
<button class="dropdown-item" role="menuitem">All files</button>
<button class="dropdown-item" role="menuitem">Pages</button>
<button class="dropdown-item" role="menuitem">Components</button>
</span>
</span>
</span>
</div>
Spinner#
A spinner shows work in progress. With .htmx-indicator it appears
only while a request runs: type below to search the mock server.
<div class="input-group max-w-sm">
<input class="input" type="search" placeholder="Saving…" disabled aria-label="Saving" />
<span class="input-group-addon input-group-addon-inline-end"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="spinner" role="status" aria-label="Loading"><path d="M21 12a9 9 0 1 1-6.22-8.56"/></svg></span>
</div>
<div class="input-group max-w-sm">
<input class="input" type="search" name="q" placeholder="Search…" aria-label="Search"
hx-get="/api/echo" hx-trigger="input changed delay:300ms" hx-target="#ig-search-result" hx-indicator="#ig-search-spinner" />
<span class="input-group-addon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg></span>
<span class="input-group-addon input-group-addon-inline-end"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="ig-search-spinner" class="spinner htmx-indicator" role="status" aria-label="Searching"><path d="M21 12a9 9 0 1 1-6.22-8.56"/></svg></span>
</div>
<p id="ig-search-result" class="muted text-sm" aria-live="polite"></p>
Textarea#
Block addons above or below a textarea make a compose box. A border-t or border-b utility on the addon draws a divider.
<div class="input-group max-w-md">
<textarea class="textarea" placeholder="Ask, search or chat…" aria-label="Prompt"></textarea>
<span class="input-group-addon input-group-addon-block-start border-b"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4M10 9H8M16 13H8M16 17H8"/></svg> <span class="input-group-text">button.css</span></span>
<span class="input-group-addon input-group-addon-block-end">
<button class="btn btn-outline btn-icon btn-rounded" aria-label="Attach"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
<span class="input-group-text ms-auto">52% used</span>
<button class="btn btn-primary btn-icon btn-rounded" aria-label="Send"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/></svg></button>
</span>
</div>
States#
Usernames can't contain spaces.
<div class="field max-w-sm">
<label class="field-label" for="ig-invalid">Username</label>
<div class="input-group">
<input class="input" id="ig-invalid" value="ada lovelace" aria-invalid="true" aria-describedby="ig-invalid-msg" />
<span class="input-group-addon">@</span>
</div>
<p class="field-error" id="ig-invalid-msg">Usernames can't contain spaces.</p>
</div>
<div class="input-group max-w-sm">
<input class="input" placeholder="Disabled" disabled aria-label="Disabled" />
<span class="input-group-addon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4" aria-hidden="true"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
</div>
Reference#
| Class | Description |
|---|---|
.input-group | Border and focus ring around a control and its addons. |
.input-group-addon | Addon at the inline start. Holds icons, text, badges, buttons, menus or spinners. |
.input-group-addon-inline-end | Addon at the end of the row. |
.input-group-addon-block-start | Full-width addon above the control. |
.input-group-addon-block-end | Full-width addon below the control. |
.input-group-text | Plain muted text inside an addon. |