contrast-matrix
A CI-first WCAG color-contrast matrix checker for design tokens, with no browser or network required.
Quickstart
pip install "contrast-matrix[yaml]"
contrast-matrix check examples/matrix.yaml
contrast-matrix check examples/matrix.yaml --format sarif --level aaa
JSON support uses only the Python standard library. Install contrast-matrix[yaml] to read YAML.
The exit status is 0 when every token passes, 1 when any token fails, and 2 for usage or
input errors.
Input schema
The root object has backgrounds, tokens, and an optional thresholds map:
thresholds: {normal: 4.5, large: 3.0, aaa_normal: 7.0}
backgrounds:
surface: "#ffffff"
surface-alt: "#f4f4f5"
overlay: "rgba(0,0,0,0.6) over #3b82f6"
tokens:
- name: text-primary
color: "#18181b"
over: [surface, surface-alt]
level: normal
- name: text-on-overlay
color: "rgba(255,255,255,0.9)"
over: [overlay]
level: large
Background keys are arbitrary names. Colors accept CSS #rgb, #rgba, #rrggbb, #rrggbbaa,
rgb(), rgba(), hsl(), and hsla(). Derived expressions accept foreground over background
and mix(first, second, t), where t ranges from 0 to 1. Each token requires a unique name, a
color, a non-empty over list of background names, and a threshold level. Built-ins are
normal (4.5), large (3.0), aaa_normal (7.0), and aaa_large (4.5); the threshold map can add
or override names. --level aaa maps normal and large to their AAA counterparts, while
--fail-under N overrides every token's threshold.
Derived expressions may use background names as operands (for example,
rgba(0,0,0,.5) over surface); references may be nested or chained, and unknown or cyclic
references are rejected as input errors.
Why a matrix?
Pairwise checkers answer whether one foreground works on one background. Design tokens often render on several surfaces, including translucent and derived colors. This tool evaluates every declared pair and reports the minimum ratio and the background that produced it, making the worst case an explicit, deterministic CI result.
The calculation follows WCAG 2.x: sRGB channels are linearized, relative luminance uses the
0.2126/0.7152/0.0722 coefficients, and contrast is (Llight + 0.05) / (Ldark + 0.05). Alpha
foregrounds are composited before comparison. This implements the WCAG 2.x contrast formula; it is
not an APCA/WCAG 3 implementation.
Output
--format table prints a compact summary. json emits the complete sorted result, including all
pairs. sarif emits SARIF 2.1.0 findings for failed tokens. Inputs, tokens, backgrounds, and JSON
keys are ordered deterministically so repeated runs produce clean diffs. See examples.
Development
python -m pip install -e '.[dev]'
pytest -q
License
Built and maintained by Gexiro Global Enterprises Ltd.
Part of the Gexiro open-source toolkit.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file contrast_matrix-0.1.1.tar.gz.
File metadata
- Download URL: contrast_matrix-0.1.1.tar.gz
- Upload date:
- Size: 22.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbb1ace24ffcaed5156adc31181c7f91c38c46c1d179b33674e98290e112cf26
|
|
| MD5 |
1497bf4459a91ab0102b434e73bb4328
|
|
| BLAKE2b-256 |
7af44eb952c308c033d183366b32b10f6a6b5932a9c0ce883ccde524b3621bd8
|
Provenance
The following attestation bundles were made for contrast_matrix-0.1.1.tar.gz:
Publisher:
release.yml on gexiro-global/contrast-matrix
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
contrast_matrix-0.1.1.tar.gz -
Subject digest:
bbb1ace24ffcaed5156adc31181c7f91c38c46c1d179b33674e98290e112cf26 - Sigstore transparency entry: 2413224300
- Sigstore integration time:
-
Permalink:
gexiro-global/contrast-matrix@1d4c52f2ec1d5b95e02ab8e5157d5dd6f6c1677b -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/gexiro-global
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1d4c52f2ec1d5b95e02ab8e5157d5dd6f6c1677b -
Trigger Event:
release
-
Statement type:
File details
Details for the file contrast_matrix-0.1.1-py3-none-any.whl.
File metadata
- Download URL: contrast_matrix-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d0dca3b5eb12f816760e340dde2be37f04ac253919773e6f22437821a2b6c89
|
|
| MD5 |
2ce08702affd9db8d50b3a40b9d0f623
|
|
| BLAKE2b-256 |
d0dbda1c7a5f1c06672629587e5b2d17b9a8615afe6dab26bea3ec2d7c6a1951
|
Provenance
The following attestation bundles were made for contrast_matrix-0.1.1-py3-none-any.whl:
Publisher:
release.yml on gexiro-global/contrast-matrix
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
contrast_matrix-0.1.1-py3-none-any.whl -
Subject digest:
6d0dca3b5eb12f816760e340dde2be37f04ac253919773e6f22437821a2b6c89 - Sigstore transparency entry: 2413224678
- Sigstore integration time:
-
Permalink:
gexiro-global/contrast-matrix@1d4c52f2ec1d5b95e02ab8e5157d5dd6f6c1677b -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/gexiro-global
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1d4c52f2ec1d5b95e02ab8e5157d5dd6f6c1677b -
Trigger Event:
release
-
Statement type: