Input group
.input-group
Input group — a control and the button that acts on it, welded into one box.
Examples
<div class="field">
<label class="field-label" for="ig-station">Station</label>
<div class="input-group">
<input class="input" id="ig-station" type="search" placeholder="Milano…" />
<button class="btn btn-primary" type="button">Search</button>
</div>
</div>One control, welded: the shared edge is drawn once and the two outer corners are the only rounded ones. Two consumers had written the arithmetic by hand.
<div class="field">
<label class="field-label" for="ig-number">Train number</label>
<div class="input-group">
<input class="input" id="ig-number" type="text" placeholder="2467" />
<button class="btn btn-primary btn-icon" type="button" aria-label="Search">
<svg class="icon" aria-hidden="true"><use href="#icon-search"></use></svg>
</button>
</div>
</div>An icon-only button carries its name on the control, never on the <svg> — the glyph is aria-hidden and the button has the aria-label.
Tokens 1
Level 2, declared on .input-group itself. Set any of them on that selector to restyle this component without touching the skin.
| Token | Default |
|---|---|
| --input-group-overlap | var(--border-width) |
Variants and states
Variants
None. It is one shape, and the page does the rest.
Inside it
.combobox.input.search.search-box.select.suggest.btn
State it reads
Read from the platform, never mirrored into a class that could disagree with it.
:focus
Before you ship it
What you have to do 4 requirements
- Label the field, and name the button — and put the label outside the group. The weld makes the button look like part of the field and it is not: an icon-only button carries its own
aria-label, and the field keeps a real<label>. Where the design has no room for label text the label is still a real element,.sr-only, in the.fieldabove — not in the group. Inside it, it is a child that draws nothing, and the seam rules below are written so that this costs nothing anyway; keeping it out is what makes the markup say what it means. - Keep the button's block padding out of the way.
.btnand.inputshare the same--target-sizefloor, so they are the same height until the button adds its own block padding around a line of text and grows past it..btn-iconhas none and needs nothing; a labelled button in a group gets--btn-padding-block: 0, which this file writes for it. - An item is
.input,.select,.btn, or one of the four wrappers —.suggest,.search,.search-box,.combobox, which are transparent here: the rules reach one level in to find the.inputor.selectthat actually draws the border. Anything else in the group — a hidden label, a hidden input — is not an item and does not move the seam. Anything deeper than one level, or any other wrapper, squares its own corners. - Two items, or three. Nothing stops more, but a field flanked on both sides is a form, not a control.
src/css/components/input-group.css · npx mostlycss add input-group