Skip to content

The accessibility standard

WCAG 2.2 AA, and zero automated errors on every page from two independent scanners. Not a target, a pass or fail.

Two scanners because they disagree. axe-core and HTML_CodeSniffer catch different things: when the site had zero axe violations, HTML_CodeSniffer found eleven errors axe does not report.

Automated checks catch perhaps a third of what matters. The manual checks below are not optional.

Check Standard
Automated scans Zero errors, axe and HTML_CodeSniffer, every page
Text contrast 4.5 to 1 against the ground it sits on
Control boundaries 3 to 1
Keyboard Every function reachable; focus always visible
Reflow No horizontal scrolling from 280px to 1920px
Reduced motion Every deck becomes a list; nothing hidden
No JavaScript Every card and quote still renders

Tab the whole page. Focus visible at every stop, order matches the visual order, nothing behind the sticky header, no traps.

Open and close the dialog both ways. Mouse and keyboard. Focus moves in, cannot leave, returns on close.

Turn on reduced motion. Count the items in each deck. Compute positions rather than eyeballing them.

Zoom to 400 percent. The decks should fall back to lists.

Each of these passed review and was caught later by a tool.

The reduced-motion block missed the recommendations fan. Eleven of twelve quotes invisible. Cause: specificity, not a missing rule.

Inert was applied to main, which contains the dialog. The dialog inherited it and stopped scrolling entirely.

A token’s comment claimed 3 to 1 and measured 2.49. The Storybook displayed the failure publicly for weeks.

aria-label replaced visible text on the pagers and the cards. Both were added during an accessibility pass. Fixing accessibility can break accessibility.

The High Contrast Mode rules were written and never applied. The @media (forced-colors: active) block sat near the top of the stylesheet, and .sdc-pager__cap set its own background further down. A media query adds no specificity, so the later rule simply won and the cap never became a border, on a page that documented it as doing so. The block now sits last in the sheet.

Both of those passed every automated scan. A scanner cannot tell you that a rule you wrote is being overridden by a rule you also wrote.

A caption sat at 3.31:1 on black because of a one-letter typo. Its rule named --text-muted; the token is --sdc-text-mute. CSS does not warn about an undefined custom property, it silently uses the fallback, and the fallback here was a hard-coded light-theme hex. It read correctly in the only theme anyone could reach, which is why nobody saw it. Found by restoring the theme toggle and scanning the palette that had never been scanned.

An inline link measured 1.02:1 against the text around it. The accent and the muted body ink sit at almost the same luminance, and prose links had no underline, at rest or on hover. The one inline link in the case studies was invisible as a link to everybody. Colour-only link styling is not a colour-blindness edge case here; it failed for every reader.

Four links were under the 24px minimum target size, between 19 and 22px: the footer wordmark and email, and the contact lists on the home page and the resume.

The PayPal logo orbit pushed the page sideways below 390px. The orbit is 680px scaled to half, so 340px, and a 320px screen has 272px of room between the gutters. Two-dimensional scrolling at 320px is a Reflow failure. The orbit is clipped now, so it bleeds off the edges instead of widening the document.

The case study styles disappeared inside the dialog. The styles were scoped to .sdc-case on <main>, and the dialog injects a case page’s <main> contents without the element itself. The pages were right, the dialog showing the same content was not. Anything scoped to an ancestor has to be checked everywhere that content gets reused.

Automated scanners flag the decorative quote marks and the progress dots as visible content hidden from screen readers. Both are correctly hidden. Exposing them would add noise for screen reader users to satisfy a tool.

Documenting a deliberate exception is part of the standard. An unexplained ignore is indistinguishable from an oversight.

Tools that scan a site and offer a widget to “fix” it do not fix it. The site meets the standard in its markup.