Skip to content

Input

.bp-field wraps a label, input, and optional hint or error message. .bp-input applies to <input>, <textarea>, and <select>. Textarea uses field-sizing: content for auto-grow where supported. All states (focus, error, disabled) are CSS-only.

Text input

Enter your legal name as it appears on your ID.

<div class="bp-field">
<label class="bp-field__label" for="name">Full name</label>
<input class="bp-input" type="text" id="name" name="name" placeholder="Jane Smith" />
<p class="bp-field__hint">Enter your legal name as it appears on your ID.</p>
</div>

Input states

<style>
.demo-field__stack { display: flex; flex-direction: column; gap: var(--bp-space-4); }
.demo-field__required { color: var(--bp-color-error); }
</style>
<div class="demo-field__stack">
<div class="bp-field">
<label class="bp-field__label" for="input-ok">Valid</label>
<input class="bp-input" type="text" id="input-ok" value="[email protected]" />
</div>
<div class="bp-field">
<label class="bp-field__label" for="input-err">
Email <span aria-hidden="true" class="demo-field__required">*</span>
</label>
<input class="bp-input" type="email" id="input-err"
value="not-an-email" required aria-required="true"
aria-invalid="true" aria-describedby="input-err-msg" />
<p class="bp-field__error" id="input-err-msg" role="alert">Enter a valid email address.</p>
</div>
<div class="bp-field">
<label class="bp-field__label" for="input-dis">Disabled</label>
<input class="bp-input" type="text" id="input-dis" value="Cannot edit" disabled />
</div>
</div>

Textarea (auto-grow)

Grows automatically as you type where field-sizing is supported.

<div class="bp-field">
<label class="bp-field__label" for="message">Message</label>
<textarea class="bp-input" id="message" name="message" rows="3" placeholder="Type your message…"></textarea>
<p class="bp-field__hint">Grows automatically as you type where field-sizing is supported.</p>
</div>

Select

<div class="bp-field">
<label class="bp-field__label" for="role">Role</label>
<select class="bp-input" id="role" name="role">
<option value="">Choose a role…</option>
<option value="designer">Designer</option>
<option value="engineer">Engineer</option>
<option value="pm">Product Manager</option>
</select>
</div>
VariableDefaultDescription
--input-bgvar(--bp-color-bg-elevated)Input background
--input-colorvar(--bp-color-text)Text color
--input-radiusvar(--bp-radius-md)Border radius
--input-paddingvar(--bp-space-3) var(--bp-space-4)Inner padding
--input-border1px solid var(--bp-color-border)Border

The error border is triggered via aria-invalid="true" or :invalid:not(:placeholder-shown) — no extra class needed.

Large search input

<style>
.demo-input--search {
--input-radius: var(--bp-radius-full);
--input-padding: var(--bp-space-3) var(--bp-space-6);
}
</style>
<div class="bp-field">
<label class="bp-field__label" for="search">Search</label>
<input class="bp-input demo-input--search" type="search" id="search" placeholder="Search components…" />
</div>
No axe violations tested 2026-05-11
  • Always pair <input> with <label for="..."> — never rely on placeholder alone.
  • Use aria-invalid="true" + aria-describedby pointing to the error message.
  • Error messages use role="alert" so they’re announced immediately by screen readers.
  • Disabled inputs don’t need aria-disabled — the disabled attribute is sufficient.
APIAvailabilityUsed forWithout itPolyfill
field-sizing: content Newly available Baseline 2024 Textarea auto-grows to fit contentFixed height via rows attributeNone needed; degrades gracefully
  • --_bg, --_color, --_radius, --_padding, --_border — component-private, do not set directly.