Six accessibility defects coding agents ship by default

6 min read

Eduardo Calvo

Eduardo CalvoWrote the skill and the detector this post measures with

Accessibility in generated code fails in a pattern, and the pattern is predictable enough to check statically. These six account for most of what we find.

1. Hover with no focus-visible

The most common defect by a wide margin. Hover is the state people demonstrate in examples, so it is the state that gets written. A control that responds to a mouse and not to a keyboard is broken for anyone who does not use a mouse — and for anyone who tabs.

2. Small text under the contrast bar

Secondary text is where this lives: a grey chosen because it looked right on the author’s screen, at 3.4:1 against paper. The bar is 4.5:1 under 18.66px, 3:1 above it. Lightness around 54% is usually the ceiling that clears both paper and a tinted surface — we found 190 findings on our own pages at 62%.

3. Tables with no overflow handling

A five-column table at 320px either overflows the page or wraps into nonsense. The fix is one wrapper with overflow-x: auto and a sticky header row, and it is almost never written.

4. Heading levels skipped

h1 then h3 because the h3 looked the right size. Screen reader users navigate by heading level; a skipped level is a missing rung. Size is a CSS decision, level is a structural one.

5. Images with no alt text, or with useless alt text

Both fail. alt="" is correct for decoration and wrong for content; alt="image" is wrong for everything.

6. Interactive divs

A div with an onClick, no role, no tabindex, no key handler. It works with a mouse and does not exist to anything else.

Why static checks are enough for these six

None of them needs a browser or a model. They are visible in source: a :hover rule with no matching :focus-visible, a computed contrast pair, a table with no wrapper, a heading sequence. That means they can run in CI on every commit, in under a second, with the same answer every time.

The ones that do need a browser — focus order, live region behaviour, whether a modal traps focus — belong in a different pass. Static checks are the floor, not the whole audit.