Form Layout Issues
Your form layout is confusing visitors — fields jump around like a tax form designed by committee. Here's how to fix the structure.
What is this?
Ever filled out a tax form where your address is on page one, your name is on page three, and your date of birth is wedged sideways in a margin? That is what a poorly laid out web form feels like. Labels are far from their inputs, related fields are scattered across the page, and the eye has no idea where to go next. The form technically works, but nobody can figure out how to use it.
Why it matters
- For your visitors: A confusing form layout makes people slow down, second-guess themselves, and make mistakes. When someone cannot tell which label belongs to which field, or when "City" and "Country" are on opposite sides of the screen for no reason, they feel stupid — and that is your fault, not theirs.
- For your business: Form completion drops dramatically when layout is unclear. Every moment of confusion is a moment where someone decides "I'll do this later" (they will not). For checkout forms, this directly costs you sales.
- The standard: Labels should be visually adjacent to their inputs — above or to the left for LTR languages. Related fields should be grouped with
<fieldset>and<legend>. Single-column layouts outperform multi-column layouts for most forms.
<form>
<fieldset>
<legend>Shipping address</legend>
<label for="street">Street</label>
<input id="street" type="text" />
<label for="city">City</label>
<input id="city" type="text" />
<label for="postcode">Postcode</label>
<input id="postcode" type="text" />
</fieldset>
</form><form>
<div style="display: flex; gap: 100px;">
<div>
<input placeholder="Street" />
<input placeholder="Postcode" />
</div>
<div>
<input placeholder="Country" />
<input placeholder="City" />
<!-- City after Country? No labels? -->
</div>
</div>
</form>How to fix it
React / Next.js
Stack fields vertically, group related ones, and keep labels directly above their inputs:
function ShippingForm() {
return (
<form className="mx-auto flex max-w-md flex-col gap-6">
<fieldset className="flex flex-col gap-4">
<legend className="text-lg font-semibold">Shipping address</legend>
<div className="flex flex-col gap-1">
<label htmlFor="street" className="text-sm font-medium">
Street address
</label>
<input id="street" type="text" className="rounded border px-3 py-2" />
</div>
<div className="grid grid-cols-2 gap-4">
<div className="flex flex-col gap-1">
<label htmlFor="city" className="text-sm font-medium">
City
</label>
<input id="city" type="text" className="rounded border px-3 py-2" />
</div>
<div className="flex flex-col gap-1">
<label htmlFor="postcode" className="text-sm font-medium">
Postcode
</label>
<input id="postcode" type="text" className="rounded border px-3 py-2" />
</div>
</div>
</fieldset>
<button type="submit" className="rounded bg-black px-4 py-2 text-white">
Continue
</button>
</form>
);
}The two-column layout for City + Postcode works because they are short, related fields. Full-width fields like "Street address" get their own row. This is the exception, not the rule — default to single-column.
Plain HTML
<form style="max-width: 28rem; margin: 0 auto;">
<fieldset style="border: none; padding: 0;">
<legend style="font-size: 1.25rem; font-weight: 600; margin-bottom: 1rem;">
Shipping address
</legend>
<div style="margin-bottom: 1rem;">
<label for="street" style="display: block; margin-bottom: 0.25rem;"> Street address </label>
<input id="street" type="text" style="width: 100%; padding: 0.5rem;" />
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">
<div>
<label for="city" style="display: block; margin-bottom: 0.25rem;"> City </label>
<input id="city" type="text" style="width: 100%; padding: 0.5rem;" />
</div>
<div>
<label for="postcode" style="display: block; margin-bottom: 0.25rem;"> Postcode </label>
<input id="postcode" type="text" style="width: 100%; padding: 0.5rem;" />
</div>
</div>
</fieldset>
</form>Bad layout is death by a thousand paper cuts. Nobody rage-quits over one misaligned label, but pile them up and your visitors quietly vanish. The cat notices every one.
How the cat scores this
The cat checks that labels are programmatically associated with inputs (via for/id or nesting), that labels appear visually near their corresponding fields, and that related fields are grouped with <fieldset>. It also flags forms wider than 600px and multi-column layouts where a single column would be clearer. Orphaned inputs with no visible label get the biggest penalty.
Further reading
- NNGroup: Website Forms Usability — research-backed form layout guidelines
- Baymard: Form Field Usability — e-commerce checkout form research
- MDN: fieldset and legend — grouping related form controls
Form Validation Issues
Your form says 'invalid input' but won't tell visitors what's actually wrong. That's like a teacher marking your test wrong without circling the answers.
Missing Input Types
Using type='text' for everything means your visitors get a QWERTY keyboard when they need a number pad. Use the right input types.