wcag_vision
wcag_vision helps you build accessible Flutter apps: check color contrast, preview how colors look under color blindness, and pull the dominant colors out of any image - no accessibility background needed to get started.
An offline, algorithmic WCAG accessibility engine for Flutter and Dart.
wcag_vision computes colour contrast exactly as specified by
WCAG 2.1 — no network calls, no heuristics,
just the spec's own math as pure, deterministic functions.
What it implements
The colour extraction module:
- K-means dominant-colour extraction —
extractDominantColorsruns deterministic Lloyd's k-means with seeded k-means++ initialisation (Arthur & Vassilvitskii, 2007) over sRGB, with configurable cluster count, convergence controls, and stratified random downsampling (one seeded draw per grid cell — alias-free on periodic patterns, reproducible via the seed) for full-resolution photos. Clustering runs in sRGB today; OKLab is the named target for a future perceptual-clustering refinement.extractDominantColorsAsyncruns the same extraction off the main isolate viaIsolate.run— designed for one-shot, single-capture analysis (tap → analyse one still frame); continuous per-frame streaming is out of scope by design.
The CVD simulation module:
- Colour vision deficiency simulation — protanopia, deuteranopia, and
tritanopia via
simulateCvd, using the physiologically-based model of Machado, Oliveira & Fairchild (2009) (severity-1.0 matrices, applied in linear RGB). Greys are invariant,CvdType.noneis the identity, and alpha passes through untouched.
The contrast module, covering:
- Relative luminance — the WCAG 2.x definition
(§ relative luminance),
including the sRGB linearization transfer function with the spec's published
0.03928threshold. - Contrast ratio —
(L1 + 0.05) / (L2 + 0.05)(§ contrast ratio), symmetric, bounded to[1.0, 21.0]. - AA / AAA conformance — thresholds from Success Criteria 1.4.3 Contrast (Minimum) and 1.4.6 Contrast (Enhanced), for both normal and large text.
- Semi-transparent colours — WCAG contrast is only defined for opaque colours, so translucent foregrounds are alpha-composited (Porter–Duff source-over) onto the background before measuring, matching browser and mainstream-tooling behaviour.
| Level | Normal text | Large text |
|---|---|---|
| AA | ≥ 4.5 : 1 | ≥ 3.0 : 1 |
| AAA | ≥ 7.0 : 1 | ≥ 4.5 : 1 |
Usage
import 'dart:ui';
import 'package:wcag_vision/wcag_vision.dart';
void main() {
const foreground = Color(0xFF767676); // mid grey
const background = Color(0xFFFFFFFF); // white
final report = evaluateContrast(foreground, background);
print(report.ratio); // ~4.54
print(report.passesAaNormal); // true (>= 4.5)
print(report.passesAaaNormal); // false (< 7.0)
// Translucent foregrounds are flattened onto the background first:
const overlay = Color.from(alpha: 0.5, red: 0, green: 0, blue: 0);
final overlayReport = evaluateContrast(overlay, background);
print(overlayReport.ratio); // contrast of the *effective* blended colour
}
Lower-level primitives (relativeLuminance, contrastRatio,
compositeOver, wcagThreshold) are also exported for callers that need
the raw calculations.
Design principles
- Fully offline and algorithmic — no data collection, no network access.
- Pure functions with deterministic outputs, unit-tested against reference values from the WCAG spec.
- Part of a Melos monorepo; consumed by the
a11y_scannerapp the same way any external user would consume it.
Libraries
- wcag_vision
- wcag_vision — an offline, algorithmic WCAG accessibility engine.