Semantic Structure

<header> <nav> <main> <footer>
Landmarks help screen reader users navigate quickly.
<button> vs <a>
Buttons trigger actions; links navigate to new locations.
<h1>...<h6>
Use a single H1 and logical heading order for structure.
<label for="id">
Every form control needs a clear label.

ARIA Basics

aria-label="Save changes"
Provide a concise label when no visible text exists.
aria-labelledby="title-id"
Use an on-page label to name a control or region.
aria-describedby="help-id"
Attach helper text or error hints.
role="dialog" aria-modal="true"
Announce modal dialogs and trap focus inside.
aria-live="polite"
Announce async updates without hijacking focus.

Keyboard and Focus

tabindex="0"
Make custom elements focusable in the natural tab order.
tabindex="-1"
Enable programmatic focus without tab stops.
:focus-visible
Show focus only for keyboard users.
Skip link: <a href="#main">
Jump past repeated nav to main content.

Forms and Validation

<fieldset> <legend>
Group related controls with a clear label.
aria-invalid="true"
Flag invalid fields and pair with error text.
aria-required="true"
Communicate required fields when HTML required is not used.
inputmode="email"
Help mobile users with the right keyboard.

Images and Media

alt="Meaningful description"
Describe intent, not pixels. Use empty alt for decorative images.
<figure> <figcaption>
Provide context and attribution for key visuals.
<track kind="captions">
Include captions for video content.

Color, Contrast, and Motion

Contrast ratios: 4.5:1 body, 3:1 large
Meet WCAG AA contrast thresholds for text.
Do not rely on color alone
Pair color with labels, icons, or patterns.
@media (prefers-reduced-motion: reduce)
Tone down animations and parallax when requested.

Quick Testing Checklist

Tab through every interactive element
Make sure focus order is logical and visible.
Use a screen reader
Spot unclear labels and missing structure.
Run Lighthouse or axe
Catch common issues fast and track regressions.