Pairette checks the contrast of an entire color palette. It pairs every color with every
other and shows which pairs are suitable for text and for graphics such as icons, charts
and infographics, on screen, in print or in both.
Graphics usually get by with less contrast than text. WCAG 2 asks 3:1 of them where
body text needs 4.5:1, and DIN 32975 sets a lower threshold for surfaces and markings
than for text.
The two media can lead to different results. A mid grey like #757575 on
white reaches 4.60:1 on screen, enough for body
text under WCAG 2. In print, measured under PSO Coated v3, the
same pair comes to K 0.69,
just short of what DIN 32975 asks of text.
Grey on white
Palette color
White
Grey
Screen (lead color)
Hex #757575
Print (calculated)
CMYK 48 / 40 / 36 / 31 CALC
Text / Bold
Grey on White:
falls short of the target in APCA and DIN, and is failed by no procedure shown.
WCAG
Measured: 4.60:1Reached: AA, meets the target
APCA
Measured: Lc72Reached: Lc60, but fails the target of Lc75
DIN
Measured: K 0.69Reached: Surfaces, but fails the target of Text at K 0.7
I'm Joschi, and I work at tollwerk, an agency for accessible communication. Every now and
then we have a project that spans media: a website, a brochure and a sign, all built on
the same corporate design. The colors then have to work on screen and on paper alike, and
in both places somebody with low vision has to be able to read what we set on them.
For the screen there are good tools. Contrast checkers measure a pair against WCAG 2, and
some, like the Contrast Grid, check
a whole palette at once. For print there is DIN 32975, with its own formula and an
additional condition. I found no tool that checks a palette against both standards,
though our projects needed exactly that.
DIN 32975 is a German standard, and we don't know whether other countries have a
comparable one for print, or which. If you do, we'd be glad to
hear about it.
Then there is APCA, a newer model of contrast perception. It is disputed: it appeared in
early drafts of WCAG 3 and has since been removed from them. In our subjective experience,
its results match our own perception quite well, and we see legitimate uses for it.
Pairette shows the results of all procedures side by side and does not rank them.
However, APCA is neither a successor to nor a replacement for WCAG 2. Laws that require
accessible contrast generally refer to WCAG 2, and will continue to do so for the time
being. If you like working with APCA, choose colors that meet both.
Tick both procedures under Evaluation, and the matrix counts the pairs that
reach your target in each of them.
So I built a small tool for our own projects. When the results began to look useful, we
decided to make it public. It is far from perfect, and there are surely gaps we haven't
noticed. If something is wrong, missing or hard to understand, please
tell us. Every piece
of feedback helps us improve Pairette, and we are grateful for it.
Building a palette
In Pairette, a palette is simply a list of named colors. It isn't saved on our server but
written into the address of the page, together with all of your settings. That means you
can bookmark a palette or send the link to someone, and they will see it exactly as you
left it. A palette holds up to 64 colors, which already makes
more than 4,000 pairs in the matrix.
If you'd like to see an example first, take a look at
our own palette. It
contains the blue, petrol and yellow of tollwerk's corporate design along with black and
white, and most of the examples further down on this page are taken from it.
To add a color, choose Add color. In the dialog that opens, you give the
color a name and enter a value for each medium you need. The field
Screen color accepts the notations you are likely to find in a style guide,
a token file or your browser's developer tools. These include hex values with three, four,
six or eight digits, the 148 named colors of CSS, and the functions rgb(),
hsl(), hwb(), lab(), lch(),
oklab(), oklch() and color() defined in
CSS Color 4. Pairette remembers which
notation you used, so a color you entered as oklch() is shown as
oklch() later on as well.
There is one case in which Pairette doesn't take a value as it is. Colors outside the range a
screen can display, which lab(), oklch() and color()
are able to describe, are moved to the nearest color a screen can show, and a note tells you
both the value you entered and the one that was measured.
A color may also be translucent, written with eight hex digits or with an opacity after a slash,
such as rgb(0 148 170 / 50%). What you see of such a color depends on what lies
beneath it, which is why a palette has a ground. The ground is white until you set another one
under Evaluation, and Pairette measures every pair the way a screen shows it,
with the background laid over the ground and the text over the result. The matrix is painted
the same way, so you see what shows through a translucent color, and its label carries a small
disc on a checkerboard. A tone scale of such a color is built from what it comes to on the
ground, and its print value from what it comes to on white paper, because a tint of it printed
there looks the same. The CSS and Design Tokens exports keep the opacity.
How much the ground matters shows with the petrol of our palette at half its opacity, next
to white. On a white page, white text on the petrol reaches only
1.86:1, because the petrol comes out as a pale
turquoise there. With the blue of our palette as the ground, the same pair reaches
6.32:1, which is enough for body text under WCAG 2.
Petrol as text on white looks the same in both, because the white covers the ground.
Petrol at 50 percent next to white, on a white page
Palette color
Petrol at 50 percent
White
Petrol at 50 percent
Screen (lead color)
RGB rgb(0 148 170 / 50%) (50 percent opaque)
Print (calculated)
CMYK 51 / 1 / 16 / 0 CALC
Color on itself, not a color pair
Text / Bold
Petrol at 50 percent on White:
fails WCAG and DIN, and falls short of the target in APCA.
WCAG
Measured: 1.86:1NOKReached: nothing, fails WCAG
APCA
Measured: Lc34Reached: Lc30, but fails the target of Lc75
DIN
Measured: K 0.32NOKReached: nothing, fails DIN
White
Screen (lead color)
Hex #ffffff
Print (calculated)
CMYK 0 / 0 / 0 / 0 CALC
Text / Bold
White on Petrol at 50 percent:
fails WCAG and DIN, and falls short of the target in APCA.
WCAG
Measured: 1.86:1NOKReached: nothing, fails WCAG
APCA
Measured: Lc-39Reached: Lc30, but fails the target of Lc75
To edit a color later on, select its name. The dialog then also lists the color in all
other notations so that you can copy them. The × next to the name removes
the color from the palette.
When you give the palette a name and choose Save under
Palette, the name becomes part of the address as well. If JavaScript is
available, Pairette additionally keeps the palette in your browser, where you can find it
again under Saved palettes. Up to 50 palettes are kept this way, and once
that limit is reached, saving another one removes the oldest.
Screen, print and spot color
Each color in a palette can have values for up to three media. There is the screen value,
there are the four ink percentages used for printing, and there is the measured value of a
spot color on paper. These values don't need to match exactly. Very vivid screen colors
can't be reproduced in four-color printing, so designers often choose a print tone that
differs from what an automatic conversion would produce, and it still counts as the same
corporate color.
Every value is either set or calculated. Values you type into a field are set. If you leave
a medium empty, Pairette calculates it from the lead color, which is the value all the
others are derived from, and marks the result with CALCcalculated
wherever it is shown. With the setting Automatic, the screen value serves as
the lead color if there is one, otherwise the print value, and otherwise the spot color.
A calculated print value is always an approximation, and for some screen colors it is not a
very good one. That's why Pairette measures how far the conversion deviates from the
original, expressed as the color difference
ΔE2000. If the
difference is greater than 5, the color is marked with a warning triangle, and its dialog
tells you how large the deviation is and recommends setting the print value yourself.
This even applies to black. Our palette doesn't specify any ink percentages for black,
so Pairette has to calculate them, and the result deviates by
ΔE 9.2 because no ink on paper is as dark as
black on a screen.
Black on white
Palette color
White
Black(1 note)
Screen (lead color)
Hex #000000
Print (calculated)
CMYK 85 / 68 / 51 / 96 CALC
Text / Bold
Black on White:
meets the target in every procedure shown.
Spot colors, on the other hand, are never calculated, because their values are measurements
of a real ink on real paper, given as L*, a* and b*. If a screen value were interpreted as
such a measurement, it would describe a paper that reflects all of the light and an ink that
reflects none of it, and pairs would pass that fail with the actual ink.
Contrast is only ever compared within the same medium, so screen values are measured
against screen values and print values against print values. If one color of a pair has no
value in a medium, the pair is not examined in that medium.
Reading the contrast matrix
A contrast matrix combines every color of a palette with every other color. Each of these
pairs is measured and checked against the requirements of the guidelines, so that you can
see at a glance which colors work well together.
The pairs have a direction. Each row uses its color as text, and each column uses its color
as background, which is why every combination appears twice, once in each direction. For
WCAG 2 this makes no difference, but APCA can rate the two directions quite differently.
The diagonal, where a color would meet itself, is left empty.
Each cell shows the pair itself, with the sample Text / Bold in the
row's color on the column's color. Below the sample you'll find, for each procedure shown,
the measured value and the rung the pair reached. At the largest cell size, a line of badges
follows with one badge for each aspect the procedure evaluates. Smaller cells leave out some
of these details, but screen readers still read out the short labels that are hidden
visually.
Reached: AA, meets the target
The rung a pair reached, which is the highest level of the procedure it meets. A filled mark means the pair
also meets your target.
Reached: AA-G/L, but fails the target of AA at 4.5:1
A rung below your target. The pair reached this level but falls short of the one you aimed for.
NOKReached: nothing, fails WCAG
No rung was reached, so the pair fails the procedure.
AA passed
An aspect the pair meets.
AAA failed
An aspect the pair misses.
Lc90 not reached,
recommended rather than required
A recommendation the pair doesn't reach. The standard prefers this level but doesn't require it.
CALCcalculated
A value that was calculated from the lead color rather than set.
Warning triangle
There is a note about this color, which you can read in its dialog.
Names, figures and marks on a color are set in black or white, depending on which of the two
is easier to read. The procedures don't always agree on that, though.
Black and white on red
Palette color
Red
Black(1 note)
Screen (lead color)
Hex #000000
Print (calculated)
CMYK 85 / 68 / 51 / 96 CALC
Text / Bold
Black on Red:
fails DIN, and falls short of the target in APCA.
WCAG
Measured: 5.25:1Reached: AA, meets the target
APCA
Measured: Lc39Reached: Lc30, but fails the target of Lc75
DIN
Measured: K 0.83NOKReached: nothing, fails DIN
White
Screen (lead color)
Hex #ffffff
Print (calculated)
CMYK 0 / 0 / 0 / 0 CALC
Text / Bold
White on Red:
falls short of the target in WCAG, APCA and DIN, and is failed by no procedure shown.
WCAG
Measured: 3.99:1Reached: AA-G/L, but fails the target of AA at 4.5:1
APCA
Measured: Lc-69Reached: Lc60, but fails the target of Lc75
DIN
Measured: K 0.66Reached: Surfaces, but fails the target of Text at K 0.7
On pure red, for example, WCAG 2 prefers black text, with a contrast of
5.25:1 compared to 3.99:1 for
white. APCA comes to the opposite conclusion and prefers white, with
Lc-69 compared to Lc39 for black.
On about a quarter of all colors, neither black nor white satisfies both procedures at the
same time.
You can decide which of the two choices you see with the setting
Text on colors under Display. With
WCAG 2, text on every color reaches at least 4.5:1.
APCA always uses APCA's choice, and
Auto does the same unless your operating system asks for
more contrast, in which case the choice of WCAG 2 is used.
Below the matrix, a sentence tells you how many pairs meet your target in all procedures
shown. It also mentions how many fall short of the target without failing, how many pairs no
requirement applies to, and how many are hidden by your result filters. Keep in mind that a
pair that wasn't examined hasn't failed either. And a pair that fails no procedure isn't
automatically usable. A contrast of 3:1 on white, for instance, doesn't fail any procedure,
but it isn't enough for body text at any level.
Contrast procedures
A contrast procedure consists of a formula and the thresholds its results are assessed
against. Pairette measures every pair with several procedures at once, some of them taken
from accessibility guidelines and some from the research behind them. Because they are based
on different models of perception, their results often differ. Which procedures apply
depends on the medium. Two of them are designed for screens, which emit light, and one for
ink on paper, which reflects it. Under Evaluation, you can choose which of
them are used.
Our own palette shows how much the results can differ. Petrol on black reaches
5.81:1, which WCAG 2 considers sufficient for body text, whereas APCA
measures only Lc-38 and finds that too little for body text.
In print, DIN 32975 even fails the pair, although its contrast of K 0.84 is above the K 0.7 required
for text. The reason is an additional condition of the standard, according to which the
lighter of the two colors has to reflect at least half of the incoming light, and petrol
reflects less than that.
Petrol on black
Palette color
Black
Petrol (Pantone 320)
Screen (lead color)
Hex #0094aa
Print
CMYK 100 / 0 / 31 / 7
Text / Bold
Petrol (Pantone 320) on Black:
fails DIN, and falls short of the target in APCA.
WCAG
Measured: 5.81:1Reached: AA, meets the target
APCA
Measured: Lc-38Reached: Lc30, but fails the target of Lc75
Screen.
The ratio of two luminances, from 1:1 to 21:1. It considers luminance only and is deliberately symmetric, so it makes no difference which of the two colors is the text.
AAA
Body text, 7:1
AAA-L
Large text (at least 18 point, which is 24 CSS pixels, or 14 point bold, about 18.7 CSS pixels), 4.5:1
AA
Body text, 4.5:1
AA-L
Large text, 3:1
AA-G
Graphics and user interface components, 3:1
WCAG, the Web Content Accessibility Guidelines, are the W3C's standard for
accessible web content. In its Understanding documents, the W3C explains the purpose
of the contrast requirements and how to meet them, in particular for
Contrast (Minimum),
Contrast (Enhanced) and
Non-text Contrast.
Screen.
Lightness contrast from Lc0 to about Lc106. APCA takes polarity into account, because dark text on a light background is perceived differently from light text on a dark background, and light text on a dark background therefore results in negative values.
Lc90
Body text, preferred
Lc75
Body text, minimum
Lc60
Other content text
Lc45
Large bold text
Lc30
Non-text, essential
The easy intro
to APCA explains what the individual levels are intended for. Pairette applies APCA
to screen colors only.
APCA was developed by Andrew Somers of Myndex Research, which holds the APCA trademark.
Pairette uses version 0.1.9 of apca-w3,
ported to PHP without changing any of its constants, under the Limited W3 License that
allows the procedure to be used for web content.
Why APCA explains why the
procedure was developed and what it sets out to do differently.
Bridge PCA,
developed by the author of APCA, evaluates contrast the same way as APCA but sets its levels high enough that a pair reaching Lc60, Lc75 or Lc90 also meets 3:1, 4.5:1 or 7:1 under WCAG 2. This only works in one direction, however. Bridge PCA rejects most of the pairs that WCAG 2 accepts at level AA, so a pair it rejects may still conform to WCAG 2. Pairette doesn't use Bridge PCA and relies on the WCAG 2 measurement itself when it comes to conformance.
Print, Spot color.
The Michelson formula applied to the luminance factor, resulting in a contrast K between 0 and 1, for surfaces that reflect light rather than emit it. In addition, the lighter of the two colors has to reflect at least half of the incoming light, otherwise the pair fails regardless of how different the two colors are.
Text
Text, K 0.7
Surfaces
Surfaces and markings, K 0.4
DIN 32975 is the German standard for designing visual information in public spaces
so that everyone can use it. It is sold by
DIN
Media and may not be passed on, which is why we don't reproduce any of its content
here. The requirements themselves are nevertheless freely available. The German
Federation of the Blind and Partially Sighted describes the formula, the thresholds and
the reflectance condition in its free brochure
Kontrastreiche Gestaltung öffentlich zugänglicher
Gebäude, and it also offers a
contrast calculator that follows the same rules.
Target and results
The target describes how good you want your palette to be, and you set it under
Evaluation. It is not part of any standard but an invention of mine.
I added it so that you can express quickly and without much effort which degree of
accessibility you are aiming for, and each procedure then translates it into one of the
levels it publishes. The following table shows which level that is.
Target
WCAG 2
APCA
DIN 32975
Minimum
AA
Body text, 4.5:1
Lc75
Body text, minimum
Text
Text, K 0.7
Enhanced
AAA
Body text, 7:1
Lc90
Body text, preferred
Text
Text, K 0.7
The names of the two targets, on the other hand, aren't invented. WCAG 2 calls its success criteria
Contrast (Minimum)
and Contrast
(Enhanced), and APCA speaks of a minimum and a preferred level. Setting a higher target
doesn't change the results of a procedure, and recommendations are still marked as
recommendations.
A rung is a level that a procedure requires, and the results you tick under
Evaluation determine which pairs the matrix shows. Rungs ticked within the same
procedure are treated as alternatives. If you tick both AA and
AA-G/L, for example, every pair that reached either of the two is
shown. Across different procedures, on the other hand, all conditions have to be met, so a
pair is only shown if every procedure that evaluated it assigned one of the rungs you ticked.
Otherwise a single lenient procedure could let the whole matrix through. A procedure that
didn't evaluate a pair never hides it.
A recommendation is never treated as a rung. APCA calls Lc90 preferable but not required, and if it were a rung, a pair that WCAG 2 rates as AAA could end up being reported as reaching nothing.
Print
A printing condition describes the combination of paper, ink and printing process, and it is
defined by an ICC profile. The same four
ink percentages result in different colors under different printing conditions, which is why
you can choose the profile under Printing condition. The
European Color Initiative publishes the
profiles commonly used in offset printing.
Pairette measures print colors through the profile using the absolute colorimetric rendering
intent. This is important because paper white is never as bright as the brightest possible
white. All other rendering intents treat paper white as if it were, and print contrast would
then appear better than it actually is on paper. For this reason, the rendering intent you
choose under Printing condition only affects how print values are calculated
from other values, and not how contrast is measured.
With Print preview under Display, the cells are painted in
their print colors, converted back to screen colors through the profile. On an uncalibrated
monitor, however, this can only give you an approximate impression.
Tone scales
A tone scale spreads a color across a fixed series of brightness levels from white to black.
All colors of the palette use the same series, and you can set the number of steps under
Display. Each tone keeps the hue of the original color as far as its
brightness allows, and the luminance it aims for is shown above its column. As an example,
have a look at the tone
scales of our palette.
The steps are evenly spaced in terms of contrast rather than lightness, so any two
neighbouring tones have the same contrast ratio, and the number above a tone indicates how
far along the way from white to black it lies. Equal steps in lightness might seem more
obvious, but then the same distance between two tones would be enough for body text in one
part of the scale and not in another.
Since WCAG 2 only considers luminance, two colors on the same tone always have a contrast of
1:1, regardless of their hues. The contrast between two colors therefore depends only on how
many tones apart they are, and once you have decided on a distance, you can choose the hues
freely. With eleven tones, neighbouring tones are ten points apart, so a distance of five
tones corresponds to fifty points.
These values apply anywhere on the scale. The middle of the scale has a contrast of
4.58:1 to both white and black, and the grey closest to it is
#757575, the same grey as in the first example on this page.
You can see this in the tone scales of the petrol and the blue from our palette. Tone 70
of either color on tone 20 of the other is fifty points apart, and the two combinations
reach the same 4.58:1,
even though the two hues have little in common.
Tone scales of petrol and blue
0
10
20
30
40
50
60
70
80
90
100
Petrol (Pantone 320)
#ffffff
#7aeeff
#00d1f1
#00b4cf
#0099b0
#008194
#006b7b
#005662
#00404a
#00292f
#000000
Blue (Pantone 648)
#ffffff
#d7ddf3
#b3bee8
#92a2de
#7388d5
#5770cc
#3b58c3
#2f469c
#243575
#16214a
#000000
Text / Bold
Tone 70 of blue on tone 20 of petrol,
4.58:1
Text / Bold
Tone 70 of petrol on tone 20 of blue,
4.58:1
Each tone can be copied and used like any other color. Its cell shows the screen value as a
hex code and, if a printing condition is available, the ink percentages as well. Open the
cell to see the tone in all other notations.
Import, export and sharing
If a palette already exists somewhere, you don't have to enter it again by hand.
Import a palette reads design
tokens, Adobe Swatch Exchange files and any plain text containing color values, and it
explains what each of these formats can carry.
Under Palette, you can export a palette as CSS custom properties, as design
tokens or as an Adobe Swatch Exchange file. Calculated values are never exported as if
someone had set them, which is why swatch files leave them out, token files mark them as
calculated and a custom property carries a comment naming what its color was calculated from
— the CMYK values under the printing condition you selected, for instance.
The notation in which each value was entered is preserved in the address and in token files,
while a swatch file has no place for it. Under Share, you can pass a palette on
through your device's share sheet, if your browser offers one, as a QR code or as a short link.
The short link opens the palette with its colors, its ground and its printing condition, but not
with the settings you are viewing it with. When the link is shared on a platform that shows
previews, the preview image contains the palette's colors and a QR code that opens it. QR Code
is a registered trademark of DENSO WAVE INCORPORATED.
The contrast matrix and the tone scales are also available as JSON, so a script or
a build can check a palette the same way you do here. Add .json to the path, as in
the matrix of our own
palette, or send application/json in the Accept header. The
parameters are those of the address you are looking at, and the answer holds what the page
shows — every color with its values, every measurement with the levels it reaches, and the
warnings the page would state above the grid. A palette sent to /import.json by
POST, as a file in the field file or as text in content, is answered
with the address of its matrix as JSON, so a script can check a token file without writing an
address by hand.
Keyboard use and JavaScript
Pairette can be used without JavaScript, because every control is either a link or a form.
In that case, a setting takes effect once you press Apply. With JavaScript,
settings take effect as soon as you change them, and the page is updated in place without
losing your focus.
In addition, two keyboard shortcuts let you move the focus directly, from anywhere on the
page except within an open dialog. Alt+Shift+P (Option+Shift+P on a Mac) moves the focus to the table of the contrast
matrix or the tone scales, and Alt+Shift+S (Option+Shift+S on a Mac) moves it to the first section of the
settings. Both shortcuts require JavaScript.
This installation
This section describes the server you are currently using, and it helps explain why print
contrast may be available on one installation but not on another.
Conversion
To convert a screen color into a print color, Pairette uses an ICC profile. The conversion
itself is done by a color engine that has to be installed on the server. Which engine is used
doesn't affect the results, since they are determined by the profile. If no engine is
available, the screen procedures continue to work, and print values are left out rather
than estimated.
FfiTransformer
Printing conditions
The following printing conditions are available on this server, and you can choose any
of them under Printing condition. For each profile, the table shows the
characterization data it is based on and the printing condition under which that data was
measured, as stated in the profile itself.
PSO Coated v3 is preselected and is used whenever an address doesn't
specify a printing condition.
Name
Characterization data
Identifier
ISO Coated v2 (ECI)
FOGRA39L Offset printing, according to ISO 12647-2:2004/Amd 1, OFCOM, paper type 1 or 2 = coated art, 115 g/m2, tone value increase curves A (CMY) and B (K)
ISOcoated_v2_eci
PSO Coated v3
FOGRA51 Offset printing, according to ISO 12647-2:2013, OFCOM, print substrate 1 = premium coated, fluorescence moderate (8-14 DeltaB according to ISO 15397), 115 g/m2, tone value increase curves A (CMYK)
PSOcoated_v3
PSO SNP Paper (ECI)
FOGRA42L Offset printing, based on ISO 12647-2:2004, OFCOM, paper type SNP (Standard Newsprint), tone value increase curves C (CMY) and D (K)
PSO_SNP_Paper_eci
PSO Uncoated v3 (FOGRA52)
FOGRA52 Offset printing, according to ISO 12647-2:2013, OFCOM, print substrate 5 = Wood-free uncoated, fluorescence high (> 14 DeltaB according to ISO 15397), 120 g/m2, tone value increase curves C (CMYK)