GitHub (opens in a new tab)
Mode
Themes
Color-vision friendly
High contrast

The audit room

A page broken on purpose. Below sits the release page for a band's debut EP — and hidden in it are twelve accessibility barriers, planted deliberately. Your job is the hunt: the heading list, the tab key, the accessibility pane, the emulations — everything the proof chapter and the reference sheets taught. A scanner finds two of the twelve — this site's own suite measured it. The other ten need you.

The contract: every barrier lives inside the framed page below, nothing outside the frame is broken, none of its links or buttons do anything real, and the answers wait at the end. The broken page is a page of its own — deliberately outside this site's styles and safety nets, so what you catch behaves the way it would in the wild. What sits below is only a half-scale preview; the hunt happens at full scale in its own tab. One warning: a barrier in there is a small badge that bounces and ignores your reduced-motion preference. If that's harmful for you, skip past the broken page, straight to the answers.

Broken on purpose · barriers 1–12 · preview at 1:2

Full-page DevTools, your own Lighthouse run — the hunt happens at full scale.

End of the broken page. Everything from here on is compliant again.

Answers

Each barrier below opens to a hint first; the answer hides one level deeper. Honest scoring is your own business — that's why there is no counter.

  1. Barrier 1: try to press the most important thing on the page
    Reveal the answer

    "Listen now" is a styled div. It looks like the primary button, but it is not focusable, not pressable by keyboard, and announces as nothing — the tree shows role generic, no name that matters.

    WCAG 2.1.1 Keyboard · Caught by: the Tab key, the accessibility pane; a scanner stays silent

    A native button element brings focus, keyboard behaviour, role, and name for free — the agent skill’s first swap.

  2. Barrier 2: one image says nothing at all
    Reveal the answer

    The EP cover has no alt attribute. A screen reader announces the filename or skips it; either way the most important image on the page is silence.

    WCAG 1.1.1 Non-text Content · Caught by: a scanner — this one axe finds

    alt="Cover of Alles auf Anfang: the band walks through darkness in a long-exposure blur" — describe what it shows, not that it is an image.

  3. Barrier 3: one of the photos is lying
    Reveal the answer

    The band photo has alt="IMG_2047.jpg". An alt exists, so scanners pass it — but hearing a camera filename is as useless as hearing nothing.

    WCAG 1.1.1 Non-text Content · Caught by: a human ear only — axe sees an alt and moves on

    Useful alt text, or alt="" if the image is decoration. The judgment is exactly what automation cannot make.

  4. Barrier 4: pull the heading list — where did the page go?
    Reveal the answer

    Tracklist, Tour, Listen, Mailing list all look like headings and are all styled paragraphs. The rotor’s heading list is empty; a screen reader user has no outline to jump by.

    WCAG 1.3.1 Info and Relationships · Caught by: the heading list (rotor / elements list), the tree

    Real h2 elements. Style is free; structure is what the shortcuts land on — the fifteen-minute plan, step two.

  5. Barrier 5: read the band’s self-description in bad light
    Reveal the answer

    The tagline is #a7a7a7 on white — roughly 2.4:1, far under the 4.5:1 minimum for body text.

    WCAG 1.4.3 Contrast (Minimum) · Caught by: a scanner, or the color picker’s contrast readout

    Pick a passing gray in DevTools — the picker draws the AA line for you — sheet A·04 shows where.

  6. Barrier 6: what is the email field actually called?
    Reveal the answer

    The signup field’s only label is its placeholder. The name vanishes the moment you type, low-contrast by design, and never a real label — the tree shows the field named by a hint that is about to disappear.

    WCAG 3.3.2 Labels or Instructions · Caught by: the accessibility pane; most scanners accept it

    A visible label element, wired with for — and an autocomplete token while you are there (1.3.5).

  7. Barrier 7: which shows can you still get into?
    Reveal the answer

    Sold-out dates differ from open ones by red text alone. With deuteranopia — or a monochrome display, or forced colors — the distinction evaporates.

    WCAG 1.4.1 Use of Color · Caught by: the vision-deficiency emulation (A·04), or any careful eye

    Say it in text — the word "ausverkauft" is actually already doing the work here; the barrier is that only its color distinguishes it from the ticket link next to it. Add an explicit "Tickets" link text and the color becomes reinforcement, not the message.

  8. Barrier 8: Tab into the signup form and watch your position vanish
    Reveal the answer

    The form controls set outline: none, and inside its own little page there is no preferences layer to overrule it. Tab into the form and your position simply vanishes — exactly where the page asks you to type.

    WCAG 2.4.7 Focus Visible · Caught by: the Tab key; scanners stay silent

    Never remove an outline without replacing it. :focus-visible styling costs one declaration.

  9. Barrier 9: pull the links list and try to tell them apart
    Reveal the answer

    Three links in a row read "click here". In the rotor’s links list — which strips their surroundings — they are indistinguishable.

    WCAG 2.4.4 Link Purpose (In Context) · Caught by: the rotor / elements list

    Name the destination: "Listen on Spotify". The sentence around the link is not what a links list reads.

  10. Barrier 10: ask the tracklist which column is which
    Reveal the answer

    The tracklist is a table of td cells only — no th, no headers. The tree shows a grid of anonymous cells; a screen reader can’t answer "which column am I in?"

    WCAG 1.3.1 Info and Relationships · Caught by: the accessibility pane; scanners only partially

    th elements with scope="col" — number, title, length — and the table starts answering questions.

  11. Barrier 11: something on this page never stops moving
    Reveal the answer

    The "OUT NOW" badge bounces forever, and its CSS never asks permission — no reduced-motion guard anywhere. Because the broken page is a document of its own, no site-wide kill rescues it either: set your OS preference or flip the Rendering-panel emulation and it keeps bouncing. That indifference is the barrier.

    WCAG 2.3.3 Animation from Interactions · Caught by: the reduced-motion emulation (A·04) — compliant motion stops, this doesn’t

    Wrap it in @media (prefers-reduced-motion: no-preference) — motion is the enhancement, stillness the default.

  12. Barrier 12: ask the mailing-list button its name, then read its label
    Reveal the answer

    The button shows "Join the mailing list" but carries aria-label="subscribe". Voice-control users say what they see — "click join the mailing list" — and nothing happens, because the visible words are not in the accessible name.

    WCAG 2.5.3 Label in Name · Caught by: the accessibility pane — axe’s rule for this exists but ships off by default (experimental)

    Let the content name it — or if ARIA must add context, start with the visible words, as the tree section showed.

About this page

The band is real; this page is not its website. Fitis exists, the EP exists, and the actual site — which is not broken on purpose — lives at fitis-band.de. Everything else here is fiction in service of the exercise.

Found barriers like these on a page you work on? The proof chapter ends with how to file what you find — impact first, one barrier per ticket, and the fix is usually a swap.