Convertisseur de couleurs et contraste WCAG
Convertit entre HEX, RGB, HSL, OKLCH et les noms de couleur CSS, et vérifie le rapport de contraste WCAG entre deux couleurs.
- HEX
#3b82f6 - RGB
rgb(59, 130, 246) - HSL
hsl(217, 91.2%, 59.8%) - OKLCH
oklch(62.31% 0.188 259.81) - NomAucun nom CSS exact
- HEX
#ffffff - RGB
rgb(255, 255, 255) - HSL
hsl(0, 0%, 100%) - OKLCH
oklch(100% 0 0) - Nom
white
C’est pour du texte courant de cette taille que le seuil de 4.5:1 est écrit.
Le grand texte n’exige que 3:1
Ce que fait cet outil
Deux tâches qui n’en font toujours qu’une. Vous avez une couleur et il vous la faut dans une autre notation : le fichier de design dit une chose, la feuille de style en veut une autre. Et vous avez deux couleurs et devez savoir si un texte de la première se lit sur la seconde. Cette page prend donc deux couleurs, affiche chacune dans tous les formats à la fois, et mesure le contraste entre elles.
Tout s’exécute dans votre navigateur. Rien d’une palette de marque encore non publiée n’a besoin de voyager jusqu’à un serveur pour être convertie.
Les cinq notations
Chacune peut être collée, et toutes ressortent :
- Hexadécimal — trois, quatre, six ou huit chiffres. Les formes courtes doublent chaque chiffre : #f0a signifie donc #ff00aa. Quatre et huit chiffres portent l’alpha en dernière position.
- RGB — les trois canaux en nombres ou en pourcentages. rgb(59, 130, 246) et rgb(59 130 246 / 50%) sont acceptés ; la forme à virgules est celle que cet outil réécrit, car c’est encore celle qu’emploie la plupart du code autour de vous.
- HSL — la teinte en degrés, puis la saturation et la clarté en pourcentages. Les teintes bouclent : 480 et -120 sont valides et valent 120 et 240.
- OKLCH — clarté, chroma et teinte dans un espace perceptuellement uniforme. La clarté s’écrit 62.8% ou 0.628.
- Noms CSS — les 148, dont rebeccapurple et les deux graphies de chaque gris. Un nom n’apparaît en sortie que si la correspondance est exacte.
Une particularité à connaître : l’hexadécimal, RGB et OKLCH font tous l’aller-retour sans changement, mais HSL pas tout à fait. Il est écrit à la précision que l’on lit réellement — des degrés entiers, une décimale de pourcentage — et cela ne suffit pas à adresser les 16,7 millions de couleurs sRGB. Convertissez un hexadécimal en HSL puis revenez, et un canal peut bouger d’une unité. L’alternative serait une sortie comme hsl(217.22, 91.19%, 59.8%), que personne n’a envie de coller. L’erreur reste très en deçà de ce que l’œil perçoit.
Pourquoi OKLCH existe
HSL semble décrire la clarté, et il ne le fait pas. Son nombre de clarté est une propriété des nombres, pas de la lumière. Le jaune pur et le bleu pur ont tous deux 50 % de clarté en HSL :
jaune #ffff00 hsl 50% oklch 96.8% bleu #0000ff hsl 50% oklch 45.2%
Chacun voit que le jaune est le plus clair des deux, et OKLCH le dit. Ce n’est pas académique : c’est pourquoi une palette construite en gardant la clarté HSL constante et en faisant tourner la teinte donne un ensemble de couleurs terriblement inégal, et pourquoi le même procédé en OKLCH donne un ensemble qui ressemble à une famille. C’est aussi pourquoi, en OKLCH, deux couleurs de même clarté ont généralement un contraste voisin sur un même fond — ce que HSL ne peut aucunement promettre.
Les deux autres nombres sont le chroma — en gros, à quel point c’est coloré, à partir de 0 pour le gris — et la teinte en degrés. Contrairement à la saturation HSL, le chroma n’est le pourcentage de rien du tout, et c’est pourquoi la valeur maximale utilisable dépend à la fois de la clarté et de la teinte.
Quand une couleur ne peut pas être affichée
OKLCH peut décrire plus de couleurs qu’un écran ordinaire ne sait en produire. Demandez une clarté de 70 % à un chroma de 0.4 et vous avez nommé un vert qui existe en principe et nulle part dans sRGB. L’outil ramène cette couleur dans la plage et la marque comme hors sRGB, plutôt que de vous rendre silencieusement autre chose.
L’avertissement n’apparaît que lorsque le rabattement change réellement la couleur obtenue. Cette distinction compte plus qu’il n’y paraît. Le rouge sRGB se situe exactement sur la limite du gamut : une valeur OKLCH publiée pour lui, arrondie à quatre décimales, tombe techniquement d’un cheveu à l’extérieur — environ deux parties pour dix mille, qui retombent sur le même octet et sont invisibles. Avertir là-dessus vous apprendrait à ignorer l’avertissement. Une couleur issue d’une palette à gamut large manque la cible de plusieurs pas entiers : le blue-500 de Tailwind v4 réclame 261 sur 255 possibles dans le canal bleu, et sur un écran sRGB ce n’est vraiment pas la couleur demandée.
Le contraste et ses trois seuils
Le rapport de contraste compare la luminance relative de deux couleurs. Il va de 1:1 pour deux couleurs identiques à 21:1 pour du noir sur blanc, et rien ne peut dépasser cela. WCAG 2.1 fixe trois seuils, et ils ne sont pas interchangeables :
- 4.5:1 pour le texte courant — tout ce qui est sous 18pt, ou sous 14pt en gras. C’est celui que l’on vise quand on dit qu’une couleur « échoue au contraste ».
- 3:1 pour le grand texte — 18pt et plus, ou 14pt gras et plus. Les grandes lettres portent davantage de signal par elles-mêmes, donc la barre est plus basse.
- 3:1 pour les contrôles et les graphiques — la bordure d’un champ, la flèche d’une liste, les barres d’un graphique. Ajouté dans WCAG 2.1 et très souvent oublié, parce que l’on vérifie son texte et jamais la boîte autour.
Le niveau AAA porte les deux premiers à 7:1 et 4.5:1. Il vaut la peine d’être visé pour le texte courant et il est réellement difficile à atteindre avec une palette de marque ; c’est AA que réclament les réglementations et les audits.
Les tailles de ces règles sont des points CSS, pas des pixels : 18pt font 24px et 14pt environ 18,7px avec les réglages par défaut. On suppose facilement qu’un titre de 20px compte comme du grand texte. Ce n’est pas le cas.
Les couleurs translucides
Un texte semi-transparent sur un fond opaque a un rapport de contraste parfaitement défini : le navigateur mélange les deux couleurs avant de peindre, et cet outil aussi. Un texte gris à 60 % d’opacité est simplement un gris plus clair une fois posé, et il est mesuré tel qu’il se pose. Les outils qui ignorent le canal alpha rapportent le rapport de la couleur que vous avez écrite et non de celle que l’on voit, ce qui le surestime toujours — un vérificateur d’accessibilité qui se trompe en votre faveur est pire que pas de vérificateur du tout.
Un fond translucide est une autre affaire, et l’outil la refuse. Ce qui se voit au travers dépend de ce qui est dessous, et ce n’est pas une question à laquelle les deux couleurs de cette page peuvent répondre. Résolvez le fond en la couleur qu’il compose réellement et mesurez celle-là.
Ce que le rapport ne vous dit pas
Un rapport conforme est un plancher, pas un verdict. Trois choses qu’il ne couvre pas :
- Le daltonisme. Un rouge et un vert de luminance identique ont un rapport proche de 1:1 et sont indistinguables pour tout le monde — mais deux couleurs peuvent être conformes et rester la seule chose qui sépare deux états, ce qui échoue pour quiconque ne les distingue pas. Ne portez jamais le sens par la seule teinte.
- Les graisses fines. La formule ne sait rien de l’épaisseur du trait. Une graisse très fine à 4.5:1 peut être plus pénible à lire qu’une graisse normale à 4:1.
- La formule elle-même. Le contraste WCAG 2 est connu pour être peu clément avec le texte clair sur fond sombre, en annonçant des rapports qui semblent plus élevés qu’ils ne se lisent. APCA, rédigé pour WCAG 3, modélise mieux ce phénomène — mais il n’est pas normatif, aucun audit ne l’accepte encore, et afficher deux scores contradictoires n’aiderait personne. D’où sa présence ici et son absence plus haut.
Une note d’implémentation pour qui compare les résultats à son propre code : la formule de luminance utilise un seuil de 0.03928, légèrement différent du 0.04045 de la définition actuelle de sRGB. WCAG cite l’ancienne valeur, c’est donc elle qui est employée ici. Coller à la spécification importe plus que la cohérence interne, et l’écart ne transforme jamais une conformité en échec.
Questions fréquentes
- Pourquoi mon hexadécimal change-t-il après un aller-retour en HSL ?
- Parce que HSL est écrit à une précision que l’on peut lire et retaper, et qui ne suffit pas à nommer toutes les couleurs sRGB. Un pas par canal au maximum se déplace, ce qui est invisible. L’hexadécimal, RGB et OKLCH font l’aller-retour exactement : utilisez l’un d’eux si vous avez besoin d’un intermédiaire sans perte.
- Que signifie « hors sRGB » ?
- La valeur OKLCH saisie nomme une couleur que votre écran ne sait pas produire ; elle a donc été ramenée à la plus proche qu’il sait produire. Les valeurs tirées de palettes à gamut large comme Tailwind v4 le font couramment. L’avertissement n’apparaît que si le rabattement change la couleur affichée : une valeur arrondie qui retombe sur le même octet ne le déclenche pas.
- Mon texte est conforme AA. Est-il accessible ?
- Il franchit une barre précise. Le rapport ne dit rien sur le fait que la couleur soit ou non la seule chose distinguant deux états, sur l’épaisseur du trait, ni sur la lisibilité de l’association pour une personne malvoyante. Traitez une conformité comme le début de la vérification, pas comme sa fin.
- Pourquoi mon titre de 20px n’est-il pas du grand texte ?
- La règle est écrite en points, pas en pixels : 18pt font 24px, et 14pt gras environ 18,7px. Un titre normal de 20px passe sous la ligne et se mesure à 4.5:1 comme n’importe quel texte courant.
- Puis-je vérifier le contraste pour un fond semi-transparent ?
- Pas à partir de deux couleurs seules : la réponse dépend de ce qui est derrière, que la page ignore. Déterminez la couleur que le fond compose et saisissez-la. Un premier plan semi-transparent, lui, fonctionne et est traité correctement : il est composé sur le fond avant la mesure, exactement comme le navigateur le peint.
- Ma palette est-elle envoyée quelque part ?
- Non. L’analyse, la conversion et le calcul du contraste s’exécutent tous dans votre navigateur ; rien de ce que vous tapez ne quitte votre appareil.