Visible labels, sized inputs

Visible labels, inputs sized to their answer, and distinct states.

From refactoring-ui, references/advanced-patterns.md (Form Design).

Placeholders vanish

Press Type for me, then find the last name.

Placeholder as labelBad
labels visible: 4 / 4
Label + hintGood
labels visible: 4 / 4
<label for="start">Start date</label>
<input id="start" placeholder="MM/DD/YYYY" inputmode="numeric">

<label for="email">Work email <span aria-hidden="true">*</span><span class="sr-only">(required)</span></label>
<input id="email" type="email" placeholder="e.g., john@example.com" required>

Width hints at the answer

Fill the sample, then drag the form width.

Everything full widthBad
width: 100%
Sized, paired, groupedGood
Contact
Address
email 400 · phone 200 · city 200 · state 150 · ZIP 100
.form   { max-width: 440px; }
.pair   { display: flex; flex-wrap: wrap; gap: 12px; }
.email  { width: min(100%, 400px); }
.phone,
.city   { width: min(100%, 200px); }
.state  { width: min(100%, 150px); }
.zip    { width: min(100%, 100px); }
.street { width: 100%; }

Five distinct input states

Pick a state, or type an email and press Tab.

Color nudge onlyBad
border: 1px solid; outline: none
Distinct statesGood

We send the receipt here.

border-color: gray-300
.input          { border: 1px solid var(--gray-300); transition: border-color 150ms, box-shadow 150ms; }
.input:focus    { border-color: var(--blue-500); box-shadow: 0 0 0 2px var(--blue-200); }
.input[aria-invalid="true"] { border-color: var(--red-500); box-shadow: 0 0 0 2px var(--red-200); }
.input:disabled { background: var(--gray-100); color: var(--gray-400); cursor: not-allowed; }
.input.is-valid { border-color: var(--green-500); }

Why it matters, pros and cons

Why it matters

A placeholder vanishes once the answer starts, so a filled form can't be checked. Width and state tell the user what fits and what went wrong.

Pros

  • Labels survive typing and autofill.
  • Screen readers get a real name.
  • Sized fields scan faster.

Cons

  • Long names and foreign postcodes break tight widths.
  • Labels cost height in dense tables.
  • Green on every field is noise.