contrastRatio
expérimentaldepuis 0.1.0@legba-core/ui
contrastRatio
Ce que ça fait
Calcule le rapport de contraste WCAG 2.x entre deux couleurs, dans [1, 21].
Signature
function contrastRatio(foreground: string | Rgb | Rgba, background: string | Rgb | Rgba): number
Paramètres
| Nom | Type | Requis | Défaut | Description |
|---|---|---|---|---|
foreground | string | Rgb | Rgba | oui | — | Couleur de premier plan (texte, icône, anneau de focus). Peut être translucide. |
background | string | Rgb | Rgba | oui | — | Couleur de fond. Doit être opaque. |
Formes de chaîne reconnues : #rgb, #rrggbb, rgb(r, g, b), rgba(r, g, b, a), rgb(r g b), rgb(r g b / a), transparent.
Les canaux et l’alpha acceptent la notation en pourcentage.
Les couleurs nommées (red) et les autres espaces colorimétriques (color(display-p3 …)) ne sont pas reconnus.
Retour
Le rapport de contraste, 1 pour deux couleurs identiques, 21 pour noir sur blanc.
Un foreground translucide est d’abord composé sur background, puis comparé.
Erreurs
| Code | Quand | Comment corriger |
|---|---|---|
TypeError | Une couleur n’est pas analysable | Passer une des formes listées ci-dessus, ou un objet Rgb |
TypeError | background a un alpha inférieur à 1 | Composer d’abord ce fond sur la couleur qu’il recouvre, puis appeler |
Exemple minimal
import { contrastRatio } from "@legba-core/ui";
const ratio = contrastRatio("#8a4e12", "#f4f2ec");
Exemple complet
import { contrastRatio, meetsContrastAA } from "@legba-core/ui";
/**
* Vérifie qu'une redéfinition de jeton reste conforme AA avant de la
* poser — à appeler depuis les tests de l'application intégratrice.
*/
function assertAccentLisible(accent: string, fond: string): void {
const ratio = contrastRatio(accent, fond);
if (!meetsContrastAA(ratio)) {
throw new Error(`${accent} sur ${fond} ne donne que ${ratio.toFixed(2)}:1, il en faut 4,5.`);
}
}
assertAccentLisible("#8a4e12", "#f4f2ec");
Pièges
- Le seuil n’est PAS dans cette fonction : elle rend un nombre, la décision
appartient à
meetsContrastAA. Comparer soi-même à4.5fonctionne, mais rate le cas du texte large (seuil 3). backgrounddoit être opaque, et la fonction lève plutôt que de supposer du blanc derrière un fond translucide. Une valeur lue pargetComputedStyle(el).backgroundColorvaut très souventrgba(0, 0, 0, 0)sur un élément sans fond propre : il faut remonter les ancêtres (frontières de Shadow DOM comprises) jusqu’au premier fond opaque avant d’appeler.- L’
opacityd’un élément n’apparaît PAS dans sacolorcalculée. Pour un texte atténué paropacity, composer soi-même la valeur (rgb(r g b / opacity)) avant de comparer, sinon le rapport mesuré est meilleur que le rapport réel. - Le calcul suit WCAG 2.x (luminance relative sRGB). Il ne met pas en œuvre APCA / WCAG 3, qui donne des valeurs incomparables.
- Un rapport conforme ne garantit pas une interface accessible : la taille de cible, le focus visible et les noms accessibles sont des critères distincts.