Skip to content

CSS Tutorial CSS Forms

Accessible Form Styling

Lesson 133 of 182 2 min read By Deepak Paswan Updated Oct 4, 2026

A good-looking form that people cannot use is a failure. These are the points that matter most, and almost all of them are CSS or HTML you already know.

1. Real labels, always visible

Every field needs a <label for>. Do not use a placeholder as the only label, because it disappears when typing and has weak contrast.

2. Enough contrast

  • Text: 4.5 : 1.
  • Field borders and focus rings: 3 : 1 against the background.

See Choosing Readable Colors.

3. Visible focus on every control

Use :focus-visible with a clear outline. See Form Focus States.

4. Large touch targets

Inputs and buttons should be at least about 44px tall. Make labels clickable so checkbox and radio targets are bigger.

5. Errors in words, tied to the field

Use text next to the field, an icon and aria-describedby. Not only a red border.

6. Respect zoom and font settings

Use rem for font size and em for padding. Do not set maximum-scale in the viewport tag. On iPhones, inputs with a font smaller than 16px cause Safari to zoom in when focused, so keep input text at 1rem or larger.

index.html
HTML
<style>
  form { max-width: 320px; font-family: system-ui, sans-serif; }
  .row { margin-bottom: 14px; }
  label { display: block; font-weight: 600; margin-bottom: 4px; }
  input { width: 100%; box-sizing: border-box; min-height: 44px; padding: 8px 12px; font: inherit; font-size: 1rem; border: 2px solid #6b6560; border-radius: 6px; }
  input:focus-visible { outline: 3px solid #1a5276; outline-offset: 2px; }
  .hint { font-size: .875rem; color: #4a4540; margin-top: 4px; }
  button { min-height: 44px; padding: 0 24px; font: inherit; font-weight: 600; background: #1a5276; color: #fff; border: 0; border-radius: 6px; }
</style>
<form>
  <div class="row"><label for="a">Full name</label><input id="a" autocomplete="name"></div>
  <div class="row"><label for="b">Email</label><input id="b" type="email" autocomplete="email" aria-describedby="bh"><p id="bh" class="hint">We only use it to send your receipt.</p></div>
  <button type="submit">Place order</button>
</form>

Wrap radio buttons and related fields in <fieldset> with a <legend>, which gives screen reader users the group’s name.

Exercise: spot the problems

A form uses placeholder text instead of labels, grey #bbb borders, outline: none on all inputs and a red border as the only error signal. List four fixes.

Show a possible solution
  1. Add real <label> elements. 2. Darken the borders to at least 3:1 contrast. 3. Replace outline: none with a visible :focus-visible style. 4. Add an error message in text, linked with aria-describedby.