CrawlCheck

Findings · 2026-09-25 · By · 0 views

We failed our own contrast check. Hover states were worse.

One invisible line in a screenshot led to 55,118 measurements at rest, then 1,878 hovers and 1,834 keyboard focuses. What failed, why static checks missed the worst of it, and what we changed.

Our own site failed WCAG contrast in more places than we expected. An at-rest check in both themes found failures as low as 1:1. A second pass with a real pointer and keyboard found 65 more failure patterns, across 242 elements, that only appear on hover, focus or after scripts run, including call-to-action buttons that fell to 1.13:1 on hover because a general link rule out-ranked the button's own hover colour. All were fixed and re-measured at zero failures.

On 25 September a screenshot arrived with one line of our own marketing copy circled: “Point it at your own domain and see the same measurements, free.” It sat in a teal box at the foot of every post, and it was nearly invisible. We measured it at 1.11 to 1. The accessible minimum for text that size is 4.5 to 1. It had shipped on every blog post and guide on this site.

That one line turned into a full audit of our own pages. This is what it found, and why the worst of it was invisible to the kind of check most sites run.

The line that started it #

The text was coloured with the site’s rule token, a faint tint meant for hairlines and borders. On a teal box that tint is itself nearly teal, so the words sat almost exactly on their own background: 1.11 to 1 in one theme and 1.15 to 1 in the other. Nobody picks a pair like that on purpose. A token meant for lines was used for words, and nothing checked the pair.

Pass one: every page, both themes, at rest #

We rendered the site’s pages in light and dark mode and measured every piece of text against the background actually behind it, with semi-transparent layers and faded parents composited in. That came to 55,118 measurements.

What failed at restWhereWorst contrast
Step numbers drawn teal on a teal discthe forms product page1.0 : 1
Registry badges faded to 55% opacity1,116 badges on the registry pages2.0 : 1
Figure labels hard-coded in light-theme colourscharts and figures, dark mode2.2 : 1
Gold labels on a pale backgroundlight mode3.4 : 1
Grey “faint” textlight mode4.3 : 1

Most of these traced back to a handful of design tokens: the faint grey, two golds and the grade colours. Darkening those in light mode and remapping the figure colours in dark mode fixed dozens of elements at once. We re-ran the check after the fix: zero failures.

Pass two: hover, focus and scripts #

A page at rest is not the page people use. We then drove a real browser across 36 pages in both themes with scripts running. It clicked every tab and step control, moved a real pointer over each distinct link and button (1,878 hovers), and moved keyboard focus onto each one (1,834 focuses). That pass found 65 failure patterns, across 242 elements, that the at-rest check had not reported.

What failed in useStateWorst contrastCause
“Get it fixed” and “Fix it all — $749”hover1.13 : 1a link-hover rule overrode the button’s own hover colour
“Scan now” and “Scan your own domain”hover1.77 : 1the same rule, on the teal buttons
The Share button on the demo reporthover1.0 : 1a site-wide button hover painted teal behind teal text
Directory filter chips and form channel rowshover1.0 : 1the same site-wide rule
The focus ring in the teal boxkeyboard focus1.61 : 1a teal ring on a teal box
Inactive steps in a walkthroughafter a click1.5 : 1faded to 30% opacity
A lead-form buttonrendered by script3.38 : 1white text on a mid-teal brand colour

The worst class is the first two rows. Our “Scan now” and “Fix it all” buttons were fine at rest and turned unreadable the moment someone moved a mouse onto them. These are the buttons that turn a reader into a customer. The cause was specificity: a general rule for links inside articles was more specific than the button’s own hover rule, so on hover the button kept its fill and took the paragraph’s text colour. A check of the page at rest can never see that, because at rest nothing is hovered.

The lead form we ship to other sites #

The last row mattered beyond this site. The same lead-form script runs on customers’ pages, and it drew a configured button colour with white text whether or not white was readable on it. It now checks the pair and, when it fails, deepens the button shade just enough to pass while keeping the brand hue and the chosen text colour. Of ten live configurations, three failed and were corrected; seven were left byte for byte as they were.

What we changed so it stays fixed #

Why a site that measures other sites missed this #

Every one of these colours was chosen by a person, and every one looked fine in the context it was chosen for. The border tint looked right on borders. The link-hover rule looked right on links. The site-wide button hover looked right on plain buttons. The failures only appeared where two reasonable rules met on one element, and nobody looks at every element in every state. That is the case for measuring rather than looking: a check does not get used to a page, and it does not skip the states that are tedious to reach.

What this does not cover #

Contrast is one accessibility check among many. It says nothing about whether a screen reader can use the page; for that side, see the nine structural things a screen reader needs. The method we used for hover and focus is written up as a step-by-step guide.

Every figure above came out of this scanner.

Point it at your own domain and see the same measurements, free.

Scan a domain — free

The main product

Found this on your own site? We fix it for $749.

Scan free to see where you stand. The fix is one site, every finding implemented and re-measured, with a sealed before and after.

Questions this post answers

Why do buttons lose contrast on hover?

Usually specificity: a more specific general rule, such as one for links inside articles, overrides the button's own hover text colour, so the fill changes but the text does not.

Can an automated contrast checker find hover problems?

Not one that measures the page at rest. Hover and focus styles only apply when an element is hovered or focused, so the check has to put the page into that state first.

What contrast ratio does WCAG require?

4.5 to 1 for normal text and 3 to 1 for large text (24px, or about 18.7px bold) under WCAG 2.1 AA. Focus indicators and other UI parts need 3 to 1 against what is next to them.

Why did transparent colours cause failures?

A tint meant for borders, such as 9 to 12 percent white, lands almost on the colour of the background behind it, so text in that colour nearly disappears.

Does fading an inactive element with opacity fail contrast?

Often. Opacity pulls the text colour toward the background; at 30 percent even dark text dropped to about 1.5 to 1.

Related findings

How anything measured in this article was measured15client identitiesone second, one address5machine filesapex and www114named agentsresolved from robots.txt24sections scoredreach, read, quoteHow anything measured here was measured15 client identities5 machine files114 named agents24 sections scoredone second, one addressapex and wwwresolved from robots.txtreach, read, quote
No account, nothing installed, and the same sequence on every domain — which is what makes one scan comparable to another. Run it on your own site.

Comments

Comments are read before they appear. Nothing is published automatically, and no account is needed.

Writing about this? Facts, live figures and marks — every number on that page is dated and traceable to a scan.

All findings · The dataset · How the dataset works