Contrast Failure Rate: The Metric Lies When the Denominator Moves

Contrast failure rate looks like the cleanest metric in an accessibility programme: text elements that fail WCAG contrast ratios, divided by text elements checked, expressed as a percentage that goes down as you fix things. It is also one of the easiest metrics to improve without fixing anything, because the denominator is under your control in ways nobody writes down.

WCAG 2.1 criterion 1.4.3 sets the thresholds, 4.5 to 1 for normal text and 3 to 1 for large text. The criterion is not the problem. The problem is what a scanner counts as a text element, and how that count changes when templates change, when a marketing page adds forty footer links, or when the crawl scope quietly widens to include the blog archive.

Three ways the rate improves on paper only

First, scope growth. Add a large, well built help centre to the crawl and the failure rate falls, because hundreds of compliant elements dilute the same fixed set of failures on the checkout. Nothing got fixed. The average moved. Second, element splits: a template change that renders one paragraph as six spans multiplies the denominator and can halve the rate in a week.

Third, the quietest one: pages dropping out of the crawl. A robots change, a login wall, a template that times out in the scanner. Failed pages do not report failures. A dashboard that does not track pages successfully scanned alongside the rate will happily show improvement caused by blindness, and this one has appeared in real programme reports, discovered months later by accident.

Report the count and the rate together, always

The discipline is simple: absolute failing element count, failure rate, and pages scanned, on the same chart, every period. If the rate falls while the count is flat and pages scanned jumped, the chart itself tells the story before anyone writes a celebratory summary. If the count falls on a stable crawl, that is a fix, and it deserves the credit the diluted version steals.

Weight by traffic while you are at it. Ten contrast failures on the payment page outrank four hundred in a legacy blog archive, because exposure is users, not elements. A programme reporting one blended rate is hiding its worst pages inside its quietest ones, usually without meaning to.

What the metric can honestly say

Used with a frozen crawl scope and a stable counting method, contrast failure rate is a fine trend line for template level remediation: fix the design system colour pairings, watch the count fall across every page that inherits them. That is its real job. It measures whether the system is getting fixed, not whether any individual page is usable.

Keep the frozen baseline visible. The moment scope changes, restart the trend and say so on the chart. A metric that survives contact with an honest methodology note is worth having. A prettier one that cannot survive the note is a liability in the first serious review, internal or otherwise.

Related reading: Keyboard Trap Count: The Metric That Should Always Read Zero, Alt Text Coverage Rate: A High Number That Can Still Mean Failure, Target Size Pass Rate: Catching Clickable Boxes Too Small to Use.

Frequently asked questions

What contrast ratio does WCAG require?

Under WCAG 2.1 criterion 1.4.3, normal text needs at least 4.5 to 1 against its background, and large text needs at least 3 to 1. Those thresholds define what counts as a failure in the rate.

How can a contrast failure rate improve without any fixes?

By growing the denominator: adding compliant pages to the crawl, splitting elements in a template change, or losing failing pages from the scan. The absolute failure count stays the same while the percentage falls.

What should be reported alongside the failure rate?

The absolute number of failing elements and the number of pages successfully scanned, on the same view. Together they expose dilution and crawl blind spots that the rate alone hides.

Is contrast failure rate still worth tracking?

Yes, as a trend on a frozen crawl scope with a stable counting method. It shows whether design system level fixes are landing. It should never be the only number, and scope changes should restart the trend openly.