InterLAB tools · Tokens · contrast · visual diff

UI consistency checker

Load your design tokens and CSS — the tool finds off-palette colours, off-scale sizes, unknown variables and low-contrast pairs. Compare the current screenshot with an approved baseline and triage every finding in one list with statuses.

Free, no sign-up

Rules v1.0 of 2026-10-13

Everything runs in this browser. Text is kept in localStorage, the approved baseline in this browser's IndexedDB, the current screenshot only in this tab's memory. Nothing is sent anywhere.

Design tokens

Paste or upload tokens: W3C DTCG JSON ($value/$type, {group.token} aliases), Style Dictionary / flat JSON, or CSS custom properties (:root plus a dark theme in .dark / [data-theme=dark]).

The format is detected automatically. In JSON, the dark theme is a top-level "dark" group.

Used to convert rem to px (usually 16).

No tokens yet. Paste them, upload a file or press “Load example”.

How the check works

  1. Tokens

    W3C DTCG JSON ($value, $type, groups, {group.token} aliases with a cycle guard), Style Dictionary JSON, or CSS custom properties. The dark theme comes from .dark, [data-theme=dark], @media (prefers-color-scheme: dark) blocks, or a "dark" group in JSON.

  2. CSS audit

    Every declaration is checked against the tokens: colours by CIEDE2000 perceptual distance; spacing, radii, font sizes and line heights against the token scale; plus unknown var(--x), !important density, z-index and fonts. Each finding has a rule ID, file:line, the declaration and a suggestion.

  3. Contrast

    Pairs are matched by name (text / foreground / on-* against background / surface) or added manually; WCAG 2.x contrast is calculated per theme: AA and AAA for normal and large text, 3:1 for non-text elements.

  4. Screenshots

    Approve a baseline (a file or a screen capture) and compare the current screenshot: a pixel diff with tolerance, anti-aliasing handling and ignore regions, a difference image and a list of changed regions with a zoomed view.

  5. Triage and report

    All findings in one list: open / to fix / accepted deviation / false positive, an owner and a note. The report is Markdown, PDF via print, and CSV; the document is JSON with re-import and versions.

Rules and thresholds

The table is generated from the same code as the check. Severity is a guide for the fix queue, not a rating of product quality.

UIC-C01

Rule
Token colour written as a literal
Severity
low
Threshold
ΔE00 ≤ 1 from a colour token: replace the literal with the variable

UIC-C02

Rule
Colour nearly matches a token
Severity
medium
Threshold
1 < ΔE00 ≤ 3: the nearest token was probably intended

UIC-C03

Rule
Off-palette colour
Severity
high
Threshold
ΔE00 > 3 from every colour token

UIC-T01

Rule
Near-duplicate colour tokens
Severity
medium
Threshold
Two different values in one theme closer than ΔE00 1, not aliases of each other (equal values for different roles are fine)

UIC-S01

Rule
Spacing off the scale
Severity
medium
Threshold
margin/padding/gap differs from every spacing token by more than 0.5 px

UIC-S02

Rule
Radius off the scale
Severity
low
Threshold
border-radius matches no radius token (except % and ≥ 999 px)

UIC-S03

Rule
Font size off the scale
Severity
medium
Threshold
font-size in px/rem matches no font-size token

UIC-S04

Rule
Line height off the scale
Severity
low
Threshold
line-height matches no line-height token of the same unit

UIC-S05

Rule
Shadow not from tokens
Severity
low
Threshold
box-shadow/text-shadow matches no shadow token (after normalisation)

UIC-V01

Rule
Unknown variable
Severity
high
Threshold
var(--x) is defined neither in the tokens nor in the audited CSS

UIC-I01

Rule
Frequent !important
Severity
medium
Threshold
≥ 3 and over 5% of the file's declarations

UIC-Z01

Rule
Magic z-index
Severity
low
Threshold
A number other than -1, 0, 1 and layer-token values

UIC-F01

Rule
Font family not from tokens
Severity
medium
Threshold
The first font-family does not match any font token

UIC-K01

Rule
Text contrast below AA
Severity
high
Threshold
Normal text: below 4.5:1 (WCAG 1.4.3)

UIC-K02

Rule
Large-text contrast below AA
Severity
high
Threshold
Large text (24 px+, or 18.66 px+ bold): below 3:1

UIC-K03

Rule
Non-text contrast below 3:1
Severity
medium
Threshold
Control boundaries, focus, icons: below 3:1 (WCAG 1.4.11)

UIC-D01

Rule
Visual difference from the baseline
Severity
medium
Threshold
A connected area of changed pixels (8 px grid); 2%+ of the frame — high severity

UIC-D02

Rule
Screenshot size changed
Severity
medium
Threshold
Width or height differs from the baseline: the common top-left area is compared
Rules v1.0 of 2026-10-13
  • Colour: ΔE00 ≤ 1 is imperceptible — the same token written as a literal; up to 3 is “nearly matches” (usually a typo); above that is “off the palette”. Alpha differences are handled separately.
  • Literals inside var(--x, …) and calc(…), variable definitions (--x: …) and SCSS variables ($x: …) are not checked for literals: they are part of the token system.
  • If there are no tokens of the needed kind (for example, no spacing scale), the rule is skipped and the report says so — the tool does not invent a scale for you.
  • Contrast: AA is 4.5:1 for normal text and 3:1 for large text, AAA is 7:1 and 4.5:1, non-text is 3:1. Thresholds are compared without rounding: 4.48:1 fails AA.
  • Defaults: channel tolerance 24/255, anti-aliasing and 1 px shifts are not counted as changes, region grid 8 px.

How the token kind is determined

If a token has a $type (DTCG), it is used; otherwise the value and the name decide. Order matters: the first match wins.

Colour

Name patterns (when $type is absent)
$type: color, or the value parses as a colour

Shadow

Name patterns (when $type is absent)
shadow, elevation

Radius

Name patterns (when $type is absent)
radius, rounded, corner

Line height

Name patterns (when $type is absent)
line-height, leading

Font size

Name patterns (when $type is absent)
font-size, text-size, fs, type-scale

Font weight

Name patterns (when $type is absent)
font-weight, weight

Font family

Name patterns (when $type is absent)
font-family, font, family, typeface

Layer (z-index)

Name patterns (when $type is absent)
z-index, z, layer

Spacing

Name patterns (when $type is absent)
spac, gap, gutter, inset, pad, margin, space, size, s, sp

Limitations

  • The source CSS is checked, not what the browser actually applied: the cascade, specificity and unused rules are not considered. Final computed styles need a browser and tests.
  • Contrast pairs by name are a heuristic: the tool does not know which text sits on which background in the design. Mark a wrong pair as a false positive and add the right one manually.
  • A semi-transparent background is composited on white (default theme) or black (dark theme) — if something else is underneath, add a pair with the final colour.
  • The visual comparison is pixel-based: screenshots of one screen must be taken in the same browser, zoom and window size. Fonts and anti-aliasing differ between operating systems — tolerance and ignore regions exist for that.
  • oklch/oklab are converted to sRGB with gamut clipping; lab(), lch(), color() and color-mix() are not parsed.

Privacy

  • Everything runs in your browser: checking never sends tokens, CSS or screenshots to a server or puts them in the page address.
  • Text, triage and versions are stored in this browser's localStorage. The approved baseline is stored in this browser's IndexedDB; the current screenshot lives only in the tab's memory. “Clear all” deletes all of it.
  • A screen capture happens only when you press the button: one frame is taken and the capture stops immediately.
  • Analytics receives only the fact of a comparison or an export and the file format — no content.
  • The result reaches us only if you send a request yourself and keep the “Attach the result” box ticked — the form shows exactly what will be sent: the token count, findings by rule, contrast failures and the share of changed screenshot pixels. Screenshots never go with the request, and neither does the CSS or the token file as a whole.

Related tools

All tools · 40
Tell us about your task — we'll review your request and get back to you

Need a full UI audit?

The InterLAB audit is a paid review of layout, accessibility, performance and code with prioritised fixes. The first short conversation about the format is free.

  • The first short conversation is free — we choose the format
  • NDA — yours or ours
  • Pricing after a brief and an agreed scope

Please do not send passwords, access keys or source code through this form — we will agree a safe way to share access separately.

By clicking the button you agree to the processing of your personal data.