It Works for Everyone or It Does Not Work
Most accessibility is not extra work — it is the HTML you already know, used correctly, plus enough contrast to read. Check a real colour pair against the standard and find out how many popular palettes fail it.
Worth reading first: div Is the Last Resort, Not the First
Most accessibility is not extra work — it is the HTML you already know, used correctly, plus enough contrast to read. Check a real colour pair against the standard and find out how many popular palettes fail it.
Semantic HTML was most of the work already
Accessibility is presented as a specialism with its own standards and audits, and the version that matters for a hand-written site is much smaller than that. If you followed chapters 4 to 10, most of it is done.
header, nav, main, footer let a screen reader user jump between regions instead of listening from the top.
A correct h1–h6 outline is how blind users skim. Skipping levels for size breaks it.
Every input joined to a label by for/id or wrapping. Otherwise the field announces nothing.
Says what the image communicates; empty alt="" for decoration; never a missing alt.
<button> for actions, <a href> for navigation. Both are focusable and announced. A div with a click handler is neither.
Says where it goes, because screen readers list links out of context.
The handful of ARIA attributes genuinely worth knowing on a static site:
<nav aria-label="Main">…</nav> <!-- distinguishes multiple navs --><button aria-expanded="false">Menu</button> <!-- open or closed state --><button aria-label="Close">×</button> <!-- names an icon-only button --><div role="status">Saved</div> <!-- announces a change politely --><span aria-hidden="true">→</span> <!-- hides decoration from readers -->Contrast is a ratio, with a number to hit
Contrast is the one part of this that is pure arithmetic, and it is the part most sites fail. The ratio between text and its background runs from 1:1 (identical) to 21:1 (black on white).
Large text, 19px semibold
Body copy at fifteen pixels. This is the size most of a page is set in, and the size the 4.5:1 threshold was written for.
Small print at twelve pixels — the hardest case.
2.85:1
contrast ratio — 1:1 to 21:1
Try “Placeholder grey” and “White on pastel”. Both look perfectly fine on a bright laptop indoors, and both fail — which is the point: contrast is not a question about your eyesight in your office. It is a question about a phone in sunlight, a cheap projector, and about eight per cent of men.
AA for normal text. This is the number to hit, and the one referenced by law in several jurisdictions.
AA for large text — 24px, or 19px bold and above. Also the minimum for meaningful borders and icons.
AAA. Stricter, and a good target for body copy on a site you control.
Purely decorative graphics, and disabled controls. Placeholder text is NOT exempt.
Try the placeholder grey in that widget. #999999 on white is one of the most common colours on the web for secondary text, and it scores about 2.8:1 — it fails at every size. So does white on most pastel buttons.
Never signal with colour alone
About one man in twelve and one woman in two hundred has some form of colour vision deficiency. Red and green, specifically, are the pair most likely to converge — which is unfortunate, because red-means-bad and green-means-good is the most common signalling convention there is.
Colour alone
A red border on an invalid field. A green tick and a red cross that differ only in hue. "Click the green button." A chart with a red line and a green line and a colour key.
Colour plus something else
A red border and an error message. A tick shape and a cross shape. A named button. A chart where one line is dashed and one is solid, labelled directly.
<div class="field field--error"> <label for="email">Email address</label> <input type="email" id="email" aria-describedby="email-error" aria-invalid="true"> <p id="email-error" class="error"> <span aria-hidden="true">⚠</span> Enter an email address, like [email protected] </p></div>The border colour is still there and still useful. It is simply no longer the only thing carrying the message — which is the whole rule.
The same applies to links in body text. If a link is only distinguished by colour, it needs at least 3:1 contrast against the surrounding text as well as 4.5:1 against the background — which is hard. Underlining them solves it completely and is the reason underlined links were the default in the first place.
Everything must work from the keyboard
Not everyone uses a mouse. People with motor impairments, people using screen readers, people with a broken trackpad, and a large number of people who are simply fast at typing.
Move to the next focusable element. Shift+Tab goes back.
Follow a link, or press a button.
Press a button, tick a checkbox, scroll the page.
Move within radio groups, selects, and sliders.
Close a dialog or a menu.
Every one of those works automatically on native elements. They work on nothing you build out of divs.
Click the address bar, then press Tab repeatedly. Can you see where focus is, at every single stop? Does the order follow the visual layout? Can you reach every link, button, and field? Can you activate everything with Enter or Space? Does focus ever disappear into something invisible?Two other keyboard traps worth knowing. A hidden menu at opacity: 0 is still focusable, so a keyboard user tabs into invisible links — use display: none or visibility: hidden. And positive tabindex values scramble the tab order for the whole page; the only values worth using are 0 and -1.
Alt text, and the images that need none
Chapter 7 covered the syntax. The judgement is what alt text should say, and it depends entirely on the image's job.
Describe what it communicates. A photo of students at a workbench: "Six students building a robot at a workbench" — not "photo" and not the filename.
alt="" — empty and present. A background flourish, a divider. Tells assistive technology to skip it, which is exactly right.
Describe the ACTION, not the picture. A magnifying glass in a search button is alt="Search", not "magnifying glass".
The alt is the text. A logo reading "CodeWithPurpose" is alt="CodeWithPurpose".
A chart needs the finding, not the shape: "Enrolment tripled between 2024 and 2026". Put the data in a table nearby if it matters.
If a caption right beside it says the same thing, alt="" avoids announcing it twice.
An accessibility pass that takes ten minutes
- ✓Tab through the whole page. Focus visible everywhere, sensible order, nothing unreachable
- ✓Check every text colour pair at 4.5:1 with the widget above
- ✓Find anything signalled by colour alone and add a shape, an icon, or a word
- ✓Check every image has an alt, and that decorative ones have an empty one
- ✓Check every form input has a label you can click
- ✓Zoom the browser to 200%: does anything overlap or get cut off?
- ✓Run Lighthouse in devtools — it catches contrast, missing alt, and label problems automatically
- ✓Read the page with CSS off. That is roughly the screen reader experience
The last thing worth saying: nearly everything here helps people who are not disabled. Captions help in a noisy room. Contrast helps in sunlight. Keyboard access helps a power user. Clear link text helps someone skimming. Good structure helps search engines. It is not a separate version of your site for a separate group of people — it is the same site, built to work in more conditions than your own.
Key takeaways
- Most accessibility is semantic HTML used correctly — landmarks, headings, labels, alt text, real buttons and links.
- The first rule of ARIA is not to use ARIA: a native element beats a div with role and tabindex.
- Text contrast must be at least 4.5:1, or 3:1 for large text. #999 on white fails at every size.
- Your bright indoor laptop is the best possible viewing condition; the ratio is what holds up outside it.
- Never signal with colour alone — add a shape, an icon, or a word. Red and green are the pair most likely to converge.
- Underlining links in body text solves the link-contrast problem completely.
- Tab, Enter, Space, arrows, and Escape all work on native elements and on nothing built from divs.
- outline: none makes a site unusable by keyboard. Style the outline; never delete it.
- opacity: 0 keeps things focusable, and positive tabindex scrambles the whole page order.
- Alt text describes what the image communicates; functional images describe the action; decorative ones get alt="".
- Lighthouse catches roughly a third of the problems automatically. Use the keyboard yourself for the rest.
- Almost all of it helps people who are not disabled too — it is one site that works in more conditions.
Quick check
Answer these to unlock the next chapter — 3 of 4 to pass. You can retake it anytime.
Answer every question to check.
Make a free account to read on
Every chapter is free — an account is how your progress, XP, and streak follow you from your laptop to your phone, and how you show up on the leaderboard. No payment, no trial.