Semantic HTML and Accessible Markup
Semantic HTML is the cheapest accessibility feature: native elements come with roles, states, keyboard behavior, and name computation. Use the element that matches meaning before adding ARIA or scripted behavior.
Core rules
- One main landmark per page; use header, nav, main, footer, aside; multiple navs need accessible names.
- Headings communicate structure; do not skip levels for styling; use CSS for size.
- Use button for actions, a href for navigation; never a clickable div.
- Every form control needs a programmatic label (label for/id, aria-labelledby, or wrapping label); placeholder is not a label. Group related controls with fieldset/legend.
- Data tables need caption, th with scope; layout tables should not be used.
- Images: meaningful alt; decorative alt=""; complex images need long description; avoid "image of" unless relevant.
- Set lang on html; give each page a unique title; provide a skip link.
Worked example
A "Save" control is <div onclick="save()">Save</div>. It is not focusable, has no role, and Enter/Space do nothing. Replace it with <button type="button">Save</button>. Reasoning: the native button supplies role=button, keyboard activation, focusability, and an accessible name from its text. If a div must be used, add role, tabindex="0", key handlers, and disabled-state handling-more fragile.
Traps
alt text that repeats the caption; empty headings used as spacers; role="button" without key support; placeholder-only labels; title attributes as names; and assuming multiple h1 elements are a failure (they are not automatically, but structure still matters).