# Kontrastforhold

## Hvad det er

Et kontrastforhold er det tal mellem 1:1 og 21:1, som WCAG bruger til at afgøre, om tekst, ikoner
og andre synlige dele af en side skiller sig nok ud fra det, de står på. Tallet sammenligner to
farvers luminans, altså deres lyshed, og ser helt bort fra farvetonen. I designsprog hedder det
også farvekontrast eller luminanskontrast, og i engelske auditrapporter står der contrast ratio pr.
farvepar. Det er den samme beregning under alle navnene.

Formlen er kort. Find den relative luminans for den lyseste farve, L1, og for den mørkeste, L2, og
divider (L1 + 0,05) med (L2 + 0,05). Relativ luminans går fra 0 for det mørkeste sort til 1 for
det lyseste hvide. For en sRGB-farve omregnes hver kanal først fra sin gammakodede værdi til
lineært lys, og bagefter vægtes de tre kanaler: 0,2126 for rød, 0,7152 for grøn og 0,0722 for blå.
To ens farver giver 1:1, og sort på hvidt giver 21:1.

Det er vægtene, der snyder øjet. Ren grøn på sort måler omkring 15,3:1, mens ren blå på sort når
cirka 2,4:1, selv om de to ser lige kraftige ud. Ren rød på hvidt lander på 3,998:1. Mellemgrå
`#767676` på hvidt måler 4,54:1, og `#777777`, ét trin lysere, måler 4,48:1. Hele regnestykket
fylder et dusin linjer:

```js
// Kontrastforhold mellem to sRGB-farver, som WCAG 2.2 definerer det
const linear = (c) => {
    const s = c / 255;
    return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
};
const luminance = (rgb) => {
    const [r, g, b] = rgb.map(linear);
    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
};
const contrast = (a, b) => {
    const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
    return (hi + 0.05) / (lo + 0.05);
};
contrast([118, 118, 118], [255, 255, 255]); // 4.54...
```

I WCAG 2.2 er forholdet en definition, og fire succeskriterier sætter tærskler på det:

- **1.4.3 Contrast (Minimum), niveau AA:** mindst 4,5:1 for tekst og billeder af tekst og mindst
  3:1 for stor tekst. Tekst i en inaktiv kontrol, ren dekoration og logoer er undtaget.
- **1.4.6 Contrast (Enhanced), niveau AAA:** mindst 7:1, og 4,5:1 for stor tekst.
- **1.4.11 Non-text Contrast, niveau AA:** mindst 3:1 mod de tilstødende farver for det, der viser
  en kontrol og dens tilstand, og for de dele af en grafik, der skal til for at forstå den.
- **2.4.13 Focus Appearance, niveau AAA:** et område af fokusindikatoren, mindst lige så stort som
  en 2 CSS-pixel tyk ramme om kontrollen, skifter med mindst 3:1 mellem fokuseret og ufokuseret
  tilstand.

Stor tekst betyder mindst 18 punkt, eller 14 punkt med fed skrift. Omregnet til CSS-pixel er det
24px, eller omkring 18,7px med fed.

## Hvorfor det betyder noget

Tærsklerne bygger på målt synstab, og det hjælper at kende baggrunden, når nogen vil bøje dem.
WCAG's Understanding-dokument tager udgangspunkt i 3:1, det minimum en ANSI-standard satte for
seere med normalt syn. Et syn på 20/40 følger med et tab i kontrastfølsomhed på omkring 1,5, så
3 × 1,5 giver 4,5:1, og samme dokument nævner, at 20/40 ofte angives som typisk synsstyrke omkring
80-årsalderen. AAA-tallet 7:1 kompenserer for et syn omkring 20/80. Fordi forholdet kun regner med
luminans, holder det for de fleste former for nedsat farvesyn, hvor en regel bygget på farvetone
ville falde igennem. Den samme margin hjælper alle, der læser på en telefon i skarpt sollys.

Den beslutning, et kontrastforhold afgør, er derfor, hvilke farver et brand må bruge til hvilket
job, og den er langt billigere at træffe i paletten end på den færdige side. En brandfarve, der
måler 3,2:1 på hvidt, har stadig opgaver: store overskrifter, ikoner og kanten om et formularfelt,
som kræver 3:1, baggrunde bag mørk tekst, dekoration og selve logoet. Brødtekst, links i en
brødtekst og pladsholdertekst kræver derimod 4,5:1, så dem må farven overlade til andre. At afgøre
det én gang i designtokens koster en eftermiddag. At opdage det efter lanceringen betyder, at hver
komponent, der har lånt farven, skal farves om, og et mørkt tema fordobler antallet af par.

Kontrast er også et af de få WCAG-krav, en maskine kan efterprøve præcist, når den kender begge
farver. Derfor dukker det op som første fund i de fleste automatiske audits og som første spørgsmål
på mange indkøbstjeklister, og niveau AA er det niveau, tilgængelighedsregler og kontrakter oftest
henviser til. At gå efter AAA's 7:1 overalt er et valg, der skal vejes: WCAG fraråder selv at kræve
AAA som politik for hele websteder, men 7:1 er et fornuftigt mål for lang læsetekst, hvor paletten
giver plads til det.

## Sådan ser det ud i praksis

To sider på dette site viser forholdet ført som et dokumenteret tal frem for et skøn med øjet.

Da sitets farvesystem blev lukket,
[fik alle 28 farver deres målte kontrast noteret](/da/portfolio/closed-the-colour-system-at-28-colours-133/),
målt på den flade, hvor farven bruges, mens de elleve brandværdier kun findes ét sted, som tokens.
Linteren kender fem fejltyper, og en af dem er et noteret forhold, der ikke passer. Til systemet
hører en fast regel, som blandt andet forbyder at skrue et dokumenteret forhold ned for designets
skyld, og den, der ønsker endnu en farve ud over de 28, må lægge dens kontrastforhold frem som en
del af begrundelsen. Siden fastsætter også en anden grænse: Ligger to farver under 0,02 fra hinanden
i et perceptuelt ensartet farverum, behandles de som samme farve skrevet på to måder. Det tal
skiller paletposter ad, og det er et andet mål end kontrast.

Det svære tilfælde var tekst over et fotografi. Siden om,
[hvordan hele sitet blev bragt op på WCAG 2.2 niveau AA](/da/portfolio/took-wcag-2-2-level-aa-across-the-whole-site-130/),
fortæller, at en automatisk regelmotor markerer den slags kontrast som noget, den ikke kan bedømme,
og at sitet indtil da havde støttet sig til et ræsonnement frem for en måling. Da der blev målt, lå
kontrasten under AA i 49 af 64 par af side og tema, og årsagen var to flader, designet aldrig havde
gjort krav på. Den kontrol, der afslørede dem, er siden gjort til en bundgrænse: Hvert par skal nu
klare AA mod den væg, buildet genererer, og ét par under grænsen er nok til, at buildet fejler.

## Hvor det går galt

**Tekst over et fotografi består i værktøjet og fejler på skærmen.** WCAG måler tekst mod dens
angivne baggrund og antager hvid, hvis der mangler en. En overskrift på et hero-billede har en
erklæret baggrundsfarve, som ikke er den, der ligger under bogstaverne, så et tjekværktøj enten
måler det forkerte par eller sender elementet videre til manuel vurdering. Mål mod de lyseste og
mørkeste pixels, teksten kan stå på, i hvert udsnit og ved hver bredde, eller læg en fast flade
eller et mørkt slør under teksten, så farven bag den er kendt.

**Et token måler 4,6:1, og siden viser 3,9:1.** Opacitet, `rgba()`-tekst, et gennemsigtigt overlag
eller en blend mode ændrer den farve, der når skærmen, så forholdet noteret for tokenet beskriver en
farve, ingen ser. Beregn forholdet for det sammensatte par, eller hold alfa helt væk fra tekst.

**En audit melder 4,49:1 som bestået.** Et forhold vist med én decimal gør 4,49 til 4,5.
Understanding-dokumentet siger udtrykkeligt, at tallene ikke afrundes: 4,499:1 opfylder ikke
4,5:1. Gem mindst to decimaler, og sammenlign den rå værdi med tærsklen.

**Det lyse tema er tjekket, og det mørke går i drift på tillid.** Hvert tema og hver tilstand, en
farve kan have, er sit eget par: hover, fokus, besøgt, fejl og pladsholdertekst, som tæller som
tekst og kræver 4,5:1. En deaktiveret kontrol er undtaget. Generér listen over par ud fra tokens,
pr. tema og pr. tilstand, og tjek listen frem for et skærmbillede.

**Tynd skrift består på papiret og blegner på skærmen.** Forholdet regnes ud fra de angivne farver,
men kantudjævning tegner hårfine snit svagere end deres CSS-farve, og Understanding-dokumentet
nævner netop dette tilfælde: sådan tekst kan bestå på papiret og alligevel læses med langt lavere
kontrast. Hæv forholdet for lette snit, eller vælg en tungere vægt af skrifttypen.

## Læs mere

- [WCAG 2.2: definitionen af contrast ratio](https://www.w3.org/TR/WCAG22/#dfn-contrast-ratio)
  — den normative definition med noterne om baggrundsfarve, hvid som standard og kantudjævning.
- [Understanding SC 1.4.3 Contrast (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)
  — hvor 4,5:1 og 3:1 kommer fra, hvordan stor tekst afgrænses, og hvorfor forhold står uafrundet.
- [Understanding SC 1.4.11 Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html)
  — 3:1-reglen for kontroller, deres tilstande og grafik, der bærer mening, med eksempler.
- [Understanding SC 1.4.6 Contrast (Enhanced)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-enhanced.html)
  — AAA-niveauet på 7:1 og de læsere, det er tænkt til.
- [CSS Color Module Level 4](https://www.w3.org/TR/css-color-4/) — sRGB's overføringsfunktion og
  de farverum, luminansformlen forudsætter.

<https://engineer.company/da/glossary/contrast-ratio/>
