ai-ops

Our homepage scores 100 on accessibility. It was still failing Level A.

Five accessibility scanners, the rule source of each one read line by line, and what they actually detect for moving content. Plus the five-minute check and the 30-minute manual pass that cover what they miss.

Open Markdown version

Our homepage scores 100 out of 100 on Lighthouse accessibility with zero failed audits. While it was scoring that, it carried a WCAG failure at Level A: a client logo band that started scrolling on page load, ran on a ninety second loop next to the rest of the page, and gave nobody a way to stop it.

No tool told us. Somebody looked at the page. Nothing we could have installed would have told us either, which we established afterwards by reading the rule source of five accessibility engines. They all look for the same two things: a <marquee> element and a <blink> element. Nobody has shipped either in about twenty years. Our band was a CSS animation, and a CSS animation is invisible to all five of them.

If your site has a hero slider, an auto-advancing carousel or a logo strip, your last green report said nothing about it either. Checking takes about five minutes, and the rest of this piece is how.

What do accessibility scanners actually detect for moving content?

Two HTML elements, <marquee> and <blink>, and nothing else. Every engine below matches this criterion by element name. Not one of them inspects a CSS animation, which is how every carousel, slider, scrolling band and parallax effect on the web has been built for the past decade.

Engine Rule tagged to WCAG 2.2.2 What the source actually matches Catches a CSS animation
axe-core 4.12.1 marquee, blink "selector": "marquee" and "selector": "blink" No
Pa11y (HTML_CodeSniffer, default runner) sniff 2_2_2 a <blink> element, or computed text-decoration: blink No
Lighthouse 13.4.0 none the 76 accessibility audits in its default config, no marquee or blink audit among them No
IBM Equal Access marquee_elem_avoid, blink_css_review context: "dom:marquee", and the literal string text-decoration:blink No
ESLint eslint-plugin-astro jsx-a11y/no-distracting-elements <marquee> and <blink> only No

Every row above comes from the tool’s own rule source. Four details are worth knowing before you rely on any of them.

  • axe-core’s entire marquee rule is an element selector. blink.json is the same file with the element name swapped. Its published table runs to 105 rules, of which exactly two carry the wcag222 tag, and those two are the element rules.
  • Pa11y’s default engine does emit a generic notice reminding a human to check moving content. Pa11y then suppresses it, because “Issues with a type of notice are not directly actionable and so they are excluded by default”. Out of the box it says nothing at all.
  • The ESLint rule is closed by design: “You cannot add any additional elements than what is offered, as the schema is only valid with the provided enumerated list”. It reads markup and never opens a stylesheet anyway.
  • Astro’s own dev toolbar audit, a sixth data point we checked, hard-codes the identical pair: const a11y_distracting_elements = ['blink', 'marquee'];.

Each of these tools does what it says on the box. axe-core’s design goal is “zero false positives (bugs notwithstanding)”, the right trade for anything allowed to fail a build. The gap is structural, and it sits in the same place for all five. That is also why the number held every time we measured it. Five Lighthouse 13.4.0 runs, mobile and desktop, starting from a rebuild of the pre-fix commit with the band confirmed animating in the built HTML and ending on the live homepage, all came back 100 out of 100 with zero failed audits.

How do you check your own site for the defect no scanner sees?

Watch the page, list what moves, and test each item against the four conditions of WCAG 2.2.2. The pass takes about five minutes per page and needs no tooling beyond a browser. What you are hunting for, all of it stock equipment on a marketing site:

  • Carousels and auto-advancing hero sliders
  • Scrolling logo and testimonial bands
  • Video that autoplays behind a headline
  • Parallax and scroll-triggered reveals
  • Animated statistic counters

Then work each item through these five steps.

  1. Load the page and watch it for ten seconds without touching anything. Write down everything that moves on its own. Scroll down and watch again, because motion triggered by an element scrolling into view counts as starting automatically under W3C’s own Understanding document.
  2. Test each item against the four conditions of WCAG 2.2.2. They are conjunctive, so all four have to hold before the criterion applies:
    • It starts automatically, with no click from the user
    • It runs longer than five seconds
    • It sits alongside other content, so a full-screen splash animation is a different case
    • It is not essential to a task the user is performing
  3. Find the control. Something on the page has to pause, stop, or hide the motion. It has to be on the page and permanently visible, so an operating system preference does not count and neither does a control that appears on hover.
  4. Reach it with the keyboard. Tab from the top of the page and confirm you can get to the control and activate it without a mouse. A pause button nobody can reach fails the same criterion it was built to satisfy.
  5. Confirm the motion actually stops. Ours is revealed by JavaScript, so a script failure would have left the button invisible and told us nothing. In DevTools, getComputedStyle(document.querySelector('.your-band')).animationPlayState should return paused after you click it, and aria-pressed should flip to true.

The pass condition for the whole check: every item on your list either fails at least one of the four conditions, or has a keyboard-reachable control that verifiably stops it.

To build the list faster, search your compiled stylesheet for infinite and animation:. Every hit is a candidate. There is a deterministic version of that tripwire too: @double-great/stylelint-a11y ships a11y/media-prefers-reduced-motion, which flags any animation or transition with no prefers-reduced-motion guard on the same selector. Against our pre-fix CSS it gives two errors and exit code 2, enough to fail a commit:

1:1  Expected .marquee is used with @media (prefers-reduced-motion)
4:1  Expected .marquee-reverse is used with @media (prefers-reduced-motion)

Be precise about what that buys you. The rule tests for one thing, a reduced-motion guard on the same selector, and a pause control is a button in the markup that no stylesheet can see. What you get is a tripwire that sends a human to look at the thing that moves, which is worth a pre-commit hook and is the whole of what a deterministic check can do here. One footnote: it matches selector by selector, so a single global block collapsing animation duration for every element still errors.

The manual pass: six areas, 20 to 30 minutes

This layer covers the motion check plus the rest of what automation cannot see, which is why a scan is a thin substitute for what a proper website audit actually surfaces. Work through it in order.

# Area Time What you do Pass condition
1 Keyboard traversal 10 min Tab through the page from the address bar. Links respond to Enter, buttons to Enter and Space, checkboxes to Space, radio groups to arrows, dialogs close on Escape and return focus to the opener Every interactive element is reachable and leavable with the keyboard alone (2.1.1 and 2.1.2, both Level A)
2 Focus visibility 3 min Tab down a long page and watch the focus indicator, including what happens under a sticky header The focused element is always visible and never entirely hidden by your own content (2.4.7 and 2.4.11, both AA)
3 Zoom and reflow 3 min Set the browser window to 1280 pixels wide and zoom the page to 400 percent, then check 200 percent text zoom No horizontal scrolling. Maps, diagrams, data tables and video are legitimately exempt (1.4.10 and 1.4.4, both AA)
4 Motion 2 min The five-step check above Every moving item either fails one of the four conditions or has a keyboard-reachable control that stops it (2.2.2, Level A)
5 Forms and errors 5 min Submit the contact form empty, then again with a badly formed email address Every field carries a visible label, and every error is described in text rather than by a red border alone (3.3.1 and 3.3.2, both Level A)
6 Structure 5 min Disable CSS and read the page top to bottom Exactly one <main>, all content inside a landmark, headings in order with no skipped levels, a skip link, and source order that still makes sense

Two habits keep this repeatable. Run it on one page per template type, usually five on a brochure site: home, a service page, the blog index, one post, and the contact form. Then record the date, the pages, and the result, because an undated pass is worth nothing three months later when somebody asks.

Row one carries the yield: a keyboard trap is a whole-page failure under WCAG Conformance Requirement 5, so a mobile menu that swallows focus takes down every page it appears on. Row six is the cheap check everybody skips, and a Tailwind grid is exactly where visual order and DOM order drift apart.

Half an hour is our own working estimate for a small static site, and nobody has timed it properly. GOV.UK says of its own basic check that “It’s likely the checks will take at least a few days”, against a much broader check set.

What is a green accessibility report actually evidence of?

A green report is a floor. Lighthouse 13.4.0 registers 76 accessibility audits in its default config, and ten of them are marked scoreDisplayMode: "manual", meaning the tool names the check and then declines to judge it. Those ten sit in a report you already generated, and nobody reads them.

  1. Interactive controls are keyboard focusable
  2. The page has a logical tab order
  3. Visual order on the page follows DOM order
  4. User focus is not accidentally trapped in a region
  5. The user’s focus is directed to new content added to the page
  6. Interactive elements indicate their purpose and state
  7. HTML5 landmark elements are used to improve navigation
  8. Offscreen content is hidden from assistive technology
  9. Custom controls have associated labels
  10. Custom controls have ARIA roles

Motion, zoom and reflow appear nowhere on that list, which is why it is a floor for the manual pass and not the whole of it. Three published figures set how high the automated floor sits, each with its caveat attached in the same breath.

Figure Source What it counts Caveat
57 percent of WCAG issues found automatically Deque, in the axe-core README issue instances A vendor claim about its own product. The underlying audit data is not published
Automated issues for 16 of the 50 Success Criteria under WCAG 2.1 AA Deque’s own coverage report success criteria with any automated coverage at all Same vendor, same report. That is 32 percent of criteria
The best of 13 tools found 40 percent of 142 planted barriers UK Government Digital Service accessibility tool audit deliberately planted barriers Last updated April 2018. Treat the ordering as informative and the percentages as stale

Which number you quote depends on the question. Count issue instances to know how much developer time automation saves. Count criteria when somebody asks whether a site conforms, because a criterion with zero automated coverage is one where the tool stays silent however many instances of something else it reports.

Automate the floor anyway, because the defects it catches are the high-frequency ones a person stops noticing at five o’clock on a Friday. Our rule for anything allowed to gate a deploy comes from content QA pipelines before you ship: same answer on the same input every time, against a rule set a person can open and read. Every engine above clears that bar, and clearing it is exactly why none of them will tell you whether a pause button exists.

The reduced-motion answer that will cost somebody a compliance claim

Ask whoever maintains your site what stops the carousel, and if the answer comes back as “the site respects reduced motion”, that answer is incomplete.

Technique C39, using the CSS prefers-reduced-motion query to prevent motion, says on its own W3C page: “This technique relates to 2.3.3 Animation from Interactions.” That criterion is Level AAA and covers motion triggered by user interaction, which puts a band starting on page load outside its scope. C39 appears nowhere among the seven techniques W3C lists for 2.2.2, and the two that fit a scrolling band are G4 and G186, both user controls.

Our fix ships both, and only one of them discharges the criterion. A reduced-motion block does nothing for the roughly everyone who has never set that preference in their operating system, which is precisely the group 2.2.2 exists to protect.

Where this stops being only a quality question

For some sites this is now law. The European Accessibility Act arrived in Austria as the Barrierefreiheitsgesetz and has applied since 28 June 2025. Two points change what you do. The rest belongs in a conversation with somebody qualified to have it.

The size exemption for service providers covers Kleinstunternehmen, which the Sozialministeriumservice defines as fewer than ten people employed and either annual turnover of at most € 2 million or a balance sheet total of at most € 2 million. Read the shape of that: the headcount test and the money test both have to hold, so a business that grows past ten people crosses the line without anything on the website changing. An in-scope provider also owes a published statement about conformity, a separate document no audit produces for you.

What to do this week

Run the five-minute motion check on your homepage. It is the page most likely to carry a band, a slider, or a hero video, and the one you can least afford to be wrong about. Anything moving with no control is a Level A failure your last green report said nothing about.

Then put the six-area pass on a date. Every automated layer we add will keep returning 100 on our homepage, including on the days something is broken in a way that matters. The band got fixed because somebody sat down and read the page, and on your site that job is either scheduled and written down or nobody is doing it. If you want it running on a schedule somebody owns, that is what our website subscription exists to carry.

If your website has become a bottleneck, let’s talk.

Start with an Audit Or email me directly