TLDR
- A scanner upgrade turned a long-tolerated img pattern into Level A failures overnight; the HTML had not changed.
- We fixed our storefront code quickly; most violations lived in CMS-generated page HTML and waited on a third-party library release (~two weeks).
- ARIA in HTML now ties img roles to whether the image has an accessible name—not alt alone; our case (alt="" + role="presentation") fits the “no name” bucket spec editors treat as allowed, often as a warning at most.
- Content generators and checkers run on different clocks; when scanners bundle stale or strict validator rules, you can fail a spec-allowed pattern at Level A while waiting on a CMS vendor to change one shared component.
When the scanner moved the goalposts
We run periodic scans with a commercial site-wide accessibility tool. After a routine software update, the report grew a batch of new Level A items. The pages had not been redeployed for that reason—the rules had.
The finding looked like this (rule wording paraphrased from the report):
Level A — ARIA 4: An img with alt="" must not have a role attribute. If the image matters, add alt text; otherwise remove the role.
Example line from the report (CDN host anonymized):
<a href="/articles/example-article">
<img
class="h-96 object-cover w-full"
alt=""
role="presentation"
src="https://cdn.example.com/articles/hero-example-01.png"
/>
</a>Decorative hero inside a link, empty alt, explicit role="presentation". We had treated that as intentional for years. The scanner now called it a hard failure.
Two places the markup lives
Our storefront application was the easy half: find role="presentation" on images with empty alt, drop the redundant role, ship. A small, repeatable change in a repo we control.
The long tail was page content from our headless CMS. Article and landing bodies are assembled in a visual editor; the serialized HTML is not hand-edited per image. The same pattern appeared dozens of times because the platform’s shared image component emitted alt="" and role="presentation" together. We opened a ticket with the vendor; roughly two weeks later a library release removed the offending role from that output. Level A cleared—but the gap between “we know the fix” and “production HTML updates” was entirely vendor latency.
That split is common on modern stacks: application code moves on your cadence; marketing HTML moves on the CMS vendor’s.
What the spec says—and why the upgrade surprised us
While we waited, I traced why a pattern spec editors discuss as permitted (sometimes redundant) was showing up as Level A in our scanner. This is a compressed version of that research—worth reading if your team argues with a checker.
The older, alt-only mental model
When the allowed roles for img table was first tightened, tools often keyed the rule almost entirely on alt:
alt="some text"→ several roles allowed.alt=""→ no role allowed.Missing
alt→ very restricted.
The W3C Nu Html Checker and similar tools reported what that table said literally—hence messages like “an img with alt="" must not have a role attribute.” A validator maintainer noted in validator#1425 that the checker was doing its job against the then-current wording.
Why that was too simplistic
Spec editor Scott O’Hara argued in html-aria#1599 that alt is not the only way an image gets an accessible name. title, aria-label, and aria-labelledby count too. Rules that looked only at alt misclassified real pages—for example, an image with no alt but a valid aria-labelledby.
The consolidated rule: “accessible name,” not “alt”
PR 453 — “Clarify and consolidate img ARIA allowances” (merged 2023) reframes three buckets:
Image situation | Roles allowed (summary) |
|---|---|
Has an accessible name (from alt, title, aria-label, aria-labelledby, …) | Functional roles (button, link, …); img allowed but not recommended |
No alt and no accessible name | none or presentation (img also allowed, not recommended) |
alt="" and no accessible name | none or presentation, allowed but not recommended |
That CMS markup—alt="", role="presentation", no aria-label—falls in the last row. It is an unnamed, decorative image explicitly marked presentational.
The ARIA in HTML implementation test cases for img treat several such combinations as not failing allowed-role rules; conformance checkers may emit warnings for redundant roles rather than errors. That is the closest thing to an editor consensus on severity.
How that becomes a Level A surprise
Timeline in outline:
Spec tightens → validator implements strict alt-only reading → developers complain (#1425).
Spec loosens and clarifies → #1599 tracks validator catch-up.
Validator (and tools that import validator rules) can lag; commenters on those threads reported rejections of markup the updated spec allows.
Commercial scanners often bundle rule packs synced from public checkers. Update the scanner → inherit stricter or stale interpretation → new failures on old HTML. You are not necessarily looking at a new user-facing regression; you may be looking at criteria drift.
Caveats: Severity (error vs warning) for a redundant presentation role is partly a checker policy choice. Our tool was within its rights to flag aggressively; we were also within ours to ask whether Level A matched the spec editors’ own tests.
Generators versus checkers
Hence the dispute we felt in the room, even after the issue was fixed:
Content generators (visual CMS platforms and similar serializers) optimize for visual authoring and ship HTML at scale. One wrong attribute on a shared image component becomes a site-wide pattern. You do not patch that in Git on Tuesday afternoon.
Checkers optimize for machine-detectable rules and change with every release. They do not wait for your CMS vendor.
Specs move on their own schedule and need human interpretation when threads, PRs, and test files disagree with your PDF report.
None of those three clocks align. A scanner update can flood the backlog with the same line item on hundreds of CMS pages while the spec editors’ tests say the pattern is at worst redundant. You are stuck between appeasing the report, arguing severity with the tool, and opening a vendor ticket for markup you never typed.
Practical triage we used:
Repo you own: fix quickly if the change is harmless (dropping a redundant
role="presentation"whenalt=""already marks decoration).Repo you do not own: document the pattern, cite PR 453 and the img test cases, escalate to the CMS vendor, and decide whether to temporarily suppress or downgrade the rule until output changes.
User impact: confirm with assistive technology. Our image sat inside a link; the link’s name came from elsewhere. Screen reader behavior—not rule ID ARIA-4 alone—set how urgent the fix felt.
Conclusion
The Level A item is resolved: application code updated, the CMS vendor shipped a fix, scans quieted. What stayed with me was the process: a rule change we did not author, applied to HTML we did not all own, elevated to the highest severity band on Monday morning.
The friction is structural. Generators ship one HTML shape everywhere; scanners ship new rule packs on upgrade; specs and validators catch up later. Teams that fare best treat the scanner as signal (something changed in your criteria), the spec and its test files as context (is this actually disallowed?), and assistive technology as verification (does anyone suffer?). Plan for CMS and checker updates as recurring weather—not as proof that your content team “broke” accessibility overnight.
