The rules everyone references are the Web Content Accessibility Guidelines, currently version 2.2. Each success criterion carries a level: A is the floor, AA is what almost every law and procurement contract requires, AAA is aspirational and not expected site-wide. When someone says "we need to be accessible", they mean WCAG 2.2 level AA unless they say otherwise.
Every report you read is organised under four principles: content must be perceivable, operable, understandable and robust. In practice, a missing image description fails the first, a keyboard trap the second, an unlabelled error message the third, and a fake button made from a styled div the fourth.
Start with tools that need no install and explain themselves.
Run all three on one page the first time. They overlap heavily, but each phrases things differently and the phrasing is how you learn the vocabulary.
| Failure | Fix |
|---|---|
| Missing image alternative text | Describe the image's purpose. If it is decoration, use alt="" — an empty alt is correct and different from no alt. |
| Form field with no label | <label for="email"> matched to id="email". Placeholder text is not a label; it disappears when you type. |
| Low contrast text | Darken the text or lighten the background until it clears the ratio below. |
No lang attribute | Add <html lang="en">. Without it a screen reader may pronounce English with the wrong voice. |
| Link text that says nothing | "Read the 2026 pricing update" instead of "read more". Screen reader users often browse links out of context. |
| Focus indicator removed | If a stylesheet sets outline: none, it must supply a visible replacement via :focus-visible. |
Contrast is a ratio between two colours, running from 1:1 (identical) to 21:1 (black on white). Under WCAG 2.2 AA you need:
Pure decoration and disabled controls are exempt. Two combinations catch almost everyone: mid-grey placeholder text on white, which typically lands near 2.8:1, and white text on a mid-tone brand colour.
You need enough to hear your own page, not fluency. On macOS press Cmd+F5 for VoiceOver, navigate with Ctrl+Option and the arrow keys, and press Ctrl+Option+U for the rotor, which lists headings, links and landmarks. On Windows, NVDA is free, starts reading immediately, opens the same elements list with Insert+F7 and quits with Insert+Q.
Then do one exercise: close your eyes and reach your main content from the top of the page. If the rotor's heading list reads as a coherent outline, your structure is sound. If it is empty, or every heading is an h1, or it is full of entries that just say "image", you have found your first real work.
The fixes above get much cheaper on a page built from real landmarks: one <header>, a <nav>, one <main>, a <footer>, and one h1 with headings descending without skipped levels. Those elements carry keyboard behaviour and announcements already, which is why a native <button> needs no ARIA while a clickable <div> needs a role, a tabindex and two key handlers to reach parity.
Add one more thing early: honour @media (prefers-reduced-motion: reduce) by cutting parallax, autoplay and large transitions. A few lines of CSS, and it matters to anyone who gets motion sickness from a scroll effect. Once a page passes cleanly, the faster audit workflow covers keeping a whole site that way.