Skip to content

Calibration

Tabler provides the taste; we provide the implementation. Calibration is how we know the two still agree.

cd poc && make calibrate
0 properties differ across 78 elements

How it works

Two static pages render the same 78 elements — a button, a card head, a badge, a nav link, a table cell, a form control, a step, a segment… — one using real Tabler, one using ours. A headless browser loads both and compares getComputedStyle property by property.

The elements are addressed by id across three fixture pages (cal, cal-parts, cal-shell), and the harness asserts that no id appears on two pages, because a silently shadowed element is a silently skipped comparison.

Reading colours is harder than it looks

getComputedStyle returns whatever notation the value arrived in. An oklab() mix read by a regex that takes the first three numbers reports a lightness and two axes as red, green and blue. So perceptual notations are resolved through a canvas — the browser parses the colour and hands back bytes.

With one exception: a canvas stores premultiplied alpha, so reading back a translucent colour costs a unit or two per channel, which is exactly the size of difference this harness exists to detect. Only oklab/oklch/lab/lch go through the canvas; color(srgb …) is converted in Python.

Deliberate exclusions

A handful of properties are excluded by name, each with a reason in the source — a width derived from content rather than the design, a shadow that is a no-op at these values, a pill radius that is "large enough" in both systems, an element with no text whose colour is therefore irrelevant.

The exclusion list is the part to be suspicious of in review. An exception list that can hide a real difference is a mute button.

What it catches that nothing else does

It earned its keep during a refactor that moved current-item styling from .is-active onto [aria-current]. Everything passed — linter clean, 31 browser tests green — and calibration reported 14 drifted properties across five elements.

The five calibration fixtures still carried the old class. With the stylesheet keyed on the attribute they were being measured unstyled, against a reference that was styled. Nothing else in the project could have found the half-done refactor, because everything else compares the system to itself.

That is the general principle: a refactor that touches a component's selector touches the fixture that measures it, and the only way to find the ones you missed is to compare against something that did not change.