When I enabled the full set of Angular accessibility template rules across MailHive's templates, the first run reported 140 violations in a product that worked and had tests. That is normal: violations accumulate wherever nothing fails when you add one. I baselined them and have been paying them down since, to 24 today. For a growing number of teams, that kind of backlog is now a legal exposure as well as a quality problem.
I wrote separately about the WCAG minimum from a designer's chair. This post is the developer's side: what the rules actually cover, and what changes in your repository on Monday. I am a developer and not a lawyer, so use this to know what to ask, and get a real legal opinion for your own company.
Who Is Actually on the Hook
Headlines make it sound as if every website is now illegal. It is narrower than that, and it depends on where you sell and who you are.
- European Union: the European Accessibility Act has applied since 28 June 2025. For the web it covers services such as e-commerce and consumer banking. Service providers that are microenterprises, meaning fewer than 10 people and no more than 2 million euros in turnover or balance sheet, are exempt. The text turns on services provided to consumers, not where the company sits, so if you sell these services to EU consumers from outside the EU, assume you are in scope.
- Canada: the 2025 digital accessibility amendments to the Accessible Canada Regulations (SOR/2025-255) apply to the federal public sector and federally regulated private businesses, such as banks, with 100 or more employees. Telecoms, broadcasters and most transport providers are mostly carved out on the public-facing side. Federal public sector web pages are due 5 December 2027, and web pages for large and medium businesses 5 December 2028. The public-facing duty covers pages created or updated on or after those dates, to the extent feasible. Businesses with 99 or fewer employees are not covered. Provinces have their own laws, such as the AODA in Ontario.
- United States: the ADA Title II rule covers state and local governments. An interim final rule from April 2026 moved the deadlines to April 2027 for those serving 50,000 people or more, and April 2028 for smaller ones. Private businesses are a separate matter, largely decided through ADA litigation and not through a rule like this one.
The technical target is close across all three. The US rule names WCAG 2.1 AA. Canada's standard and the EU's supporting standard are based on EN 301 549. Canada's edition currently incorporates WCAG 2.1 AA, and it is referenced as amended from time to time, so it moves with newer editions. Deque reports that v4.1.1, with WCAG 2.2 AA, was published in September 2026. So build to WCAG 2.2 AA. It covers the 2.1 criteria, but EN 301 549 adds requirements of its own, so check those too if those rules apply to you.
Most of the Errors Are Boring, and That Is Good News
The 2026 WebAIM Million found detectable WCAG failures on 95.9% of the top million home pages, with an average of 56.1 errors per page. The useful part: 96% of all detected errors fall into six categories.
- Low contrast text: 83.9% of home pages.
- Missing image alternative text: 53.1%.
- Missing form input labels: 51%.
- Empty links: 46.3%.
- Empty buttons: 30.6%.
- Missing document language: 13.5%.
Component defaults, design tokens and lint rules can prevent most of these. So this is a place where a small developer effort moves real numbers. And there is one more figure you should know: pages with ARIA averaged 59.1 errors, against 42 for pages without it. That is a correlation, since complex pages use more ARIA. Reaching for ARIA first adds ways to be wrong. Use a real button.
Step 1: Fail on New Violations Today
Static rules are free, fast, and catch problems before the browser opens. For Angular, angular-eslint ships an accessibility config for templates. For React, the equivalent is eslint-plugin-jsx-a11y.
// eslint.config.js, inside tseslint.config(...), simplified
{
files: ['**/*.html'],
extends: [
...angular.configs.templateRecommended,
...angular.configs.templateAccessibility,
],
}On an existing app, expect a number like that. Do not make it a cleanup project, because that project will lose to the next feature. Record the existing violations with ESLint bulk suppressions, so that only new ones fail the build. Vendored templates you do not own need a decision too: exempting them keeps the build green, but they can still block a user, so track them. The baseline stops the bleeding. It does not fix anything: every suppressed entry is a known item to burn down, not an accepted one. Burn it down, starting with the shared components and then the flows people cannot avoid, like sign-in and checkout. That is how MailHive went from 140 to 24.
Step 2: Test the Rendered Page
Lint sees templates, not the result. Contrast depends on computed styles, and heading order only appears at runtime. Axe finds both, though heading order is a best-practice rule, so add the best-practice tag if you want it. It plugs into the end-to-end suite you probably already have, and it is open source and free.
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('checkout has no detectable WCAG A or AA violations', async ({ page }) => {
await page.goto('/checkout');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
.analyze();
expect(results.violations).toEqual([]);
});Start with your three most important flows, and test each one in its important states, such as with the error messages showing. Axe only sees what is on the screen when it runs.
Step 3: Accept What No Tool Will Catch
Deque's own study of over 2,000 audits found automated testing covered about 57% of issues by volume. It is a vendor's figure and a good one for them, so treat it as the optimistic end. Even so, something like four issues in ten need a person. A tool can tell you an image has alt text. It cannot tell you the text is nonsense. It can tell you a button has a name, not that focus went somewhere sensible after clicking it.
In a single-page app, the manual failures cluster in the same places. Check these by hand, keyboard only, before a feature is called done:
- Route change: focus moves to the new content and the page title changes. In a SPA focus does not move for you, and Angular only updates the title if you define one on the route. A screen reader user can get no signal that anything happened.
- Dialogs: focus goes in, stays in, and returns to the trigger on close. Angular CDK's a11y module and the native dialog element with showModal both solve most of it. Do not write your own unless they cannot cover your case.
- Form errors: the error is tied to its input with aria-describedby and is announced after submit. A red border announces nothing.
- Dynamic updates: a toast or a results count needs a live region. On Angular, LiveAnnouncer in the CDK does this.
- Custom widgets: any div with a click handler. Tab to it and try to operate it with Enter and Space, and check you can see where focus is.
Screen reader testing is the next layer. NVDA is free on Windows and VoiceOver ships with Macs and iPhones. My WCAG post covers those pairings, so I will not repeat them. Put the keyboard pass in your definition of done first. It takes minutes and finds a lot.
Do Not Buy Your Way Out with an Overlay
A one-line script that promises compliance is a tempting answer to a legal deadline. In April 2025 the US Federal Trade Commission finalized an order requiring accessiBe to pay 1 million dollars over claims that its plugin could make any website WCAG compliant. The order bars such claims without evidence. An overlay runs on top of the code that has the problem. Fix the code.
Things Developers Forget Are Also in Scope
- PDFs and documents. For the federal public sector and businesses with 500 or more employees, Canada's rules cover downloadable documents, so check your invoice generator.
- Accessibility statements. Canada requires them every year from the federal public sector and businesses with 500 or more employees, and the EU has its own information duties for services. Find out who owns this in your company before someone asks.
- Training and records. Canada's rules require training for people working on digital technologies, and keeping records for four years. Not your job alone, but raise it.
- Third-party widgets. Your payment iframe, chat bubble and consent banner are part of the page your user has to get through.
The First Sprint I Would Run
- Day 1: turn on the lint rules, baseline the existing violations, and fail on new ones.
- Day 2: fix the shared components first. One fixed button or input component clears every usage at once.
- Day 3: add axe to your end-to-end tests for your top three flows.
- Day 4: do a keyboard-only pass on those flows, and file what you find as bugs, with severity.
- Day 5: add the keyboard pass to your definition of done, and ask your company which of these laws applies to it.
Lint and axe do not make you compliant. They stop you getting worse. The rest takes a person.
References
- Directive (EU) 2019/882, European Accessibility Act. https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32019L0882
- Government of Canada. Summary of the digital accessibility rules. https://www.canada.ca/en/employment-social-development/programs/accessible-canada/regulations-summary-act/amendment.html
- US Department of Justice. ADA Title II web rule. https://www.ada.gov/resources/2024-03-08-web-rule/
- Canada Gazette. Regulations Amending the Accessible Canada Regulations, SOR/2025-255. https://gazette.gc.ca/rp-pr/p2/2025/2025-12-17/html/sor-dors255-eng.html
- Deque. EN 301 549 v4.1.1 is final. https://www.deque.com/blog/en-301-549-v4-1-1-is-final-what-changed-what-it-means-and-what-you-should-do/
- W3C. WCAG 2.2. https://www.w3.org/TR/WCAG22/
- WebAIM. The WebAIM Million, 2026. https://webaim.org/projects/million/
- Deque. Automated testing study. https://www.deque.com/blog/automated-testing-study-identifies-57-percent-of-digital-accessibility-issues
- FTC. Final order requiring accessiBe to pay 1 million dollars. https://www.ftc.gov/news-events/news/press-releases/2025/04/ftc-approves-final-order-requiring-accessibe-pay-1-million
- angular-eslint template accessibility rules. https://github.com/angular-eslint/angular-eslint
- eslint-plugin-jsx-a11y. https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
- Playwright accessibility testing. https://playwright.dev/docs/accessibility-testing
- Angular CDK accessibility. https://material.angular.dev/cdk/a11y