Niveau 6 — Les Couleurs

Les Couleurs CSS

Maîtriser tous les formats de couleurs, créer des palettes accessibles, implémenter le dark mode et manipuler les couleurs avec les fonctions modernes du CSS.

1. Comprendre les couleurs en CSS

En une phrase : Les couleurs CSS sont des représentations numériques de la lumière perçue — chaque format (HEX, RGB, HSL, OKLCH…) encode les mêmes informations couleurs différemment, et le choix du format influence la maintenabilité, l'accessibilité et la précision du code.
TYPES DE COULEURS CSS
━━━━━━━━━━━━━━━━━━━━━

  ┌── NOMMÉES ─────────────────────────┐
  │  red, blue, tomato, rebeccapurple   │
  │  148 couleurs nommées standard      │
  └─────────────────────────────────────┘

  ┌── HEXADÉCIMALES ───────────────────┐
  │  #ff0000   → 6 chiffres hex        │
  │  #f00      → 3 chiffres (raccourci)│
  │  #ff000080 → 8 chiffres (avec alpha)│
  └─────────────────────────────────────┘

  ┌── RGB / RGBA ──────────────────────┐
  │  rgb(255 0 0)                      │
  │  rgb(255 0 0 / 0.5)                │
  └─────────────────────────────────────┘

  ┌── HSL / HSLA ──────────────────────┐
  │  hsl(0 100% 50%)                   │
  │  hsl(0 100% 50% / 0.5)             │
  └─────────────────────────────────────┘

  ┌── HWB ─────────────────────────────┐
  │  hwb(0 0% 0%)                      │
  └─────────────────────────────────────┘

  ┌── ESPACES MODERNES ────────────────┐
  │  oklch(0.6 0.2 25)                 │
  │  oklab(0.5 -0.1 0.1)              │
  │  lab(50 40 -20)                    │
  │  lch(50 45 340)                    │
  └─────────────────────────────────────┘

  ┌── FONCTIONS ───────────────────────┐
  │  color-mix()    light-dark()        │
  │  color()        currentColor        │
  └─────────────────────────────────────┘

Inventaire complet des formats de couleurs CSS

2. Les formats de couleurs en détail

2.1 Couleurs nommées

/* Les 148 couleurs nommées du CSS */
.texte-rouge  { color: red; }
.fond-vert    { background-color: green; }
.bordure-bleue { border-color: blue; }

/* Les plus utiles */
.link         { color: currentColor; }     /* Couleur héritée */
.transparent  { background: transparent; } /* Valeur spécifique */
.invisible    { visibility: hidden; }

/* Exemples moins connus mais utiles */
.titel        { color: tomato; }        /* Rouge doux */
.accent       { color: rebeccapurple; } /* Violet élégant */
.subtle       { color: slategray; }     /* Gris bleuté */
.warning      { color: darkorange; }    /* Orange vif */
.success      { color: seagreen; }      /* Vert naturel */
.info         { color: steelblue; }     /* Bleu professionnel */
tomato
#ff6347
rebeccapurple
#663399
steelblue
#4682b4
seagreen
#2e8b57
coral
#ff7f50
darkslateblue
#483d8b
crimson
#dc143c
mediumvioletred
#c71585
Format Pros Cons Quand l'utiliser
Nommées Lisible, rapide à écrire Peu précises, 148 limitées, pas de variation Prototypage rapide, cas simples

2.2 HEX — Hexadécimal

/* Syntaxe HEX — notation la plus répandue */
.rouge-6   { color: #ff0000; }    /* 6 chiffres : #RRGGBB */
.rouge-3   { color: #f00; }       /* 3 chiffres : #RGB (raccourci) */
.rouge-8   { color: #ff000080; }  /* 8 chiffres : #RRGGBBAA (avec alpha) */
.rouge-4   { color: #f008; }      /* 4 chiffres : #RGBA */

/* Les 3 formats sont équivalents : */
.c1 { color: #ff6347; }  /* version 6 */
.c2 { color: #f64; }     /* version 3 → même chose */

/* Pas de sensibilité à la casse */
.c3 { color: #FF6347; }  /* ✅ Identique */
.c4 { color: #ff6347; }  /* ✅ Identique */

/* Exemples pratiques */
.primaire    { background: #2563eb; }
.secondaire  { background: #7c3aed; }
.succes      { background: #16a34a; }
.erreur      { background: #dc2626; }
.fond        { background: #f8fafc; }
.texte       { color: #1e293b; }
.muted       { color: #64748b; }
Format Pros Cons Quand l'utiliser
HEX Compact, universel, outils de design l'utilisent Non intuitif, pas de alpha en 3/6 chiffres, difficile de varier la luminosité Design tokens existants, copier depuis Figma/Photoshop

2.3 RGB / RGBA

/* rgb() — rouge, vert, bleu (0-255 ou 0%-100%) */
.primaire {
  background: rgb(37, 99, 235);       /* Ancienne syntaxe (virgules) */
  background: rgb(37 99 235);         /* Nouvelle syntaxe (espaces) */
  background: rgb(14.5% 38.8% 92.2%);/* Avec pourcentages */
}

/* Avec alpha (transparence) */
.demi-transparent {
  background: rgba(37, 99, 235, 0.5); /* Ancienne syntaxe */
  background: rgb(37 99 235 / 0.5);   /* Nouvelle syntaxe */
}

/* Opacité variations */
.opacite-10 { background: rgb(37 99 235 / 0.1); }
.opacite-20 { background: rgb(37 99 235 / 0.2); }
.opacite-50 { background: rgb(37 99 235 / 0.5); }
.opacite-80 { background: rgb(37 99 235 / 0.8); }
rgb(37 99 235)
rgb(37 99 235 / 0.8)
rgb(37 99 235 / 0.5)
rgb(37 99 235 / 0.3)
rgb(37 99 235 / 0.1)

2.4 HSL / HSLA

hsl() représente les couleurs avec la teinte (hue), la saturation et la luminosité. C'est le format le plus intuitif pour créer des variantes d'une couleur.
/* hsl(teinte, saturation%, luminosité%) */
.primaire {
  color: hsl(217, 91%, 60%);
  color: hsl(217 91% 60%);          /* Nouvelle syntaxe */
}

/* Avec alpha */
.demi {
  background: hsl(217, 91%, 60%, 0.5);
  background: hsl(217 91% 60% / 0.5); /* Nouvelle syntaxe */
}

/* Créer une palette à partir d'une teinte unique */
:root {
  --hue: 217;
  --sat: 91%;
}

.primary-50  { background: hsl(var(--hue) var(--sat) 97%); }
.primary-100 { background: hsl(var(--hue) var(--sat) 94%); }
.primary-200 { background: hsl(var(--hue) var(--sat) 86%); }
.primary-300 { background: hsl(var(--hue) var(--sat) 76%); }
.primary-400 { background: hsl(var(--hue) var(--sat) 66%); }
.primary-500 { background: hsl(var(--hue) var(--sat) 57%); }  /* Base */
.primary-600 { background: hsl(var(--hue) var(--sat) 46%); }
.primary-700 { background: hsl(var(--hue) var(--sat) 39%); }
.primary-800 { background: hsl(var(--hue) var(--sat) 31%); }
.primary-900 { background: hsl(var(--hue) var(--sat) 22%); }

/* Teintes autour du cercle chromatique */
.rouge   { color: hsl(0, 90%, 55%); }    /* 0° */
.orange  { color: hsl(25, 90%, 55%); }   /* 25° */
.jaune   { color: hsl(48, 90%, 55%); }   /* 48° */
.vert    { color: hsl(142, 70%, 45%); }  /* 142° */
.bleu    { color: hsl(217, 91%, 60%); }  /* 217° */
.violet  { color: hsl(270, 80%, 60%); }  /* 270° */
.rose    { color: hsl(330, 80%, 60%); }  /* 330° */
0° Rouge
25° Orange
48° Jaune
142° Vert
217° Bleu
270° Violet
330° Rose
Format Pros Cons Quand l'utiliser
HSL Intuitif, facile de créer des variantes (luminosité) Pas perceptuellement uniforme (hsl(50,100%,50%) est beaucoup plus lumineux que hsl(250,100%,50%)) Création de palettes, quand on comprend le modèle

2.5 HWB — Hue, Whiteness, Blackness

/* hwb(teinte blanc% noir%) */
.rouge { color: hwb(0 0% 0%); }      /* Rouge pur */
.pastel {
  background: hwb(217 0% 0%);        /* Bleu pur */
  background: hwb(217 40% 0%);       /* Bleu pastel (ajout de blanc) */
}
.sombre {
  background: hwb(217 0% 40%);       /* Bleu foncé (ajout de noir) */
}

/* Avantage de HWB : plus intuitif pour "éclaircir" ou "assombrir" */
.bleu-clair  { background: hwb(217 0% 10%); }  /* Un peu plus sombre */
.bleu-fonce  { background: hwb(217 10% 0%); }  /* Un peu plus clair */

/* Avec alpha */
.alpha { background: hwb(0 0% 0% / 0.5); }

2.6 OKLCH — Le format moderne

oklch() utilise l'espace colorimétrique OKLCH (OK Lightness, Chroma, Hue). C'est le format le plus recommandé pour les palettes modernes car il est perceptuellement uniforme : modifier la luminosité de 0.1 produit un changement perçu identique quelle que soit la teinte.
/* oklch(luminosité chroma teinte) */
/* L : 0 (noir) → 1 (blanc) */
/* C : 0 (gris neutre) → ~0.4 (très saturé) */
/* H : 0-360 (teinte en degrés) */

.bleu { color: oklch(0.62 0.19 250); }
.rouge { color: oklch(0.63 0.25 29); }
.vert { color: oklch(0.72 0.19 142); }
.jaune { color: oklch(0.93 0.18 100); }
.gris { color: oklch(0.55 0 0); }

/* Palette harmonieuse : même chroma, luminosité variable */
:root {
  --ok-chroma: 0.15;
  --ok-hue: 250;

  --ok-50:  oklch(0.97 var(--ok-chroma) var(--ok-hue));
  --ok-100: oklch(0.93 var(--ok-chroma) var(--ok-hue));
  --ok-200: oklch(0.87 var(--ok-chroma) var(--ok-hue));
  --ok-300: oklch(0.79 var(--ok-chroma) var(--ok-hue));
  --ok-400: oklch(0.70 var(--ok-chroma) var(--ok-hue));
  --ok-500: oklch(0.62 var(--ok-chroma) var(--ok-hue));
  --ok-600: oklch(0.53 var(--ok-chroma) var(--ok-hue));
  --ok-700: oklch(0.44 var(--ok-chroma) var(--ok-hue));
  --ok-800: oklch(0.35 var(--ok-chroma) var(--ok-hue));
  --ok-900: oklch(0.25 var(--ok-chroma) var(--ok-hue));
}

/* Avec alpha */
.alpha { background: oklch(0.62 0.19 250 / 0.5); }

/* Avantage : créer des variantes sombres/claires est cohérent */
/* En HSL : hsl(50,100%,50%) est très lumineux, hsl(250,100%,50%) est sombre */
/* En OKLCH : une luminosité de 0.6 est TOUJOURS la même intensité perçue */
50
200
400
500
700
900

2.7 Comparaison des formats

Format Syntaxe Perceptuellement uniforme Facilité de variation Browser support
HEX #2563eb Non Difficile 100%
RGB rgb(37 99 235) Non Moyenne 100%
HSL hsl(217 91% 60%) Non Bonne 100%
HWB hwb(217 0% 0%) Non Bonne 96%+
OKLCH oklch(0.62 0.19 250) Oui Excellente 93%+

3. color-mix() et light-dark()

3.1 color-mix() — Mélanger des couleurs

/* color-mix(in espace-colorimétrique, couleur1 proportion, couleur2 proportion) */
.melange {
  /* Mélange 50/50 de bleu et rouge dans OKLCH */
  background: color-mix(in oklch, #2563eb 50%, #dc2626 50%);
}

/* Variantes d'une couleur de base */
:root {
  --primary: #2563eb;
}

.primary-50  { background: color-mix(in oklch, var(--primary) 10%, white); }
.primary-100 { background: color-mix(in oklch, var(--primary) 20%, white); }
.primary-200 { background: color-mix(in oklch, var(--primary) 30%, white); }
.primary-300 { background: color-mix(in oklch, var(--primary) 40%, white); }
.primary-400 { background: color-mix(in oklch, var(--primary) 50%, white); }
.primary-500 { background: var(--primary); }
.primary-600 { background: color-mix(in oklch, var(--primary) 80%, black); }
.primary-700 { background: color-mix(in oklch, var(--primary) 60%, black); }
.primary-800 { background: color-mix(in oklch, var(--primary) 40%, black); }
.primary-900 { background: color-mix(in oklch, var(--primary) 20%, black); }

/* Transparence avec transparent */
.bleu-20pct {
  background: color-mix(in oklch, #2563eb 20%, transparent);
}

/* Hover automatique */
.btn:hover {
  background: color-mix(in oklch, var(--btn-bg) 85%, black);
}
.btn:active {
  background: color-mix(in oklch, var(--btn-bg) 70%, black);
}

/* Mélanger avec une couleur personnalisée */
.violet {
  background: color-mix(in oklch, #2563eb, #7c3aed);
  /* Résultat : une teinte entre bleu et violet */
}

/* Espace colorimétrique : in srgb, in hsl, in oklch, in oklab, in lab, in xyz */
.precis  { background: color-mix(in oklch, #2563eb 50%, #dc2626); }
.classic { background: color-mix(in srgb, #2563eb 50%, #dc2626); }
50% bleu
50% rouge
70% bleu
30% rouge
30% bleu
70% blanc
50% bleu
50% transparent

3.2 light-dark() — Mode sombre sans media query

/* light-dark(couleur-pour-mode-clair, couleur-pour-mode-sombre) */
/* Nécessite color-scheme sur :root */
:root {
  color-scheme: light dark;
}

/* Utilisation */
body {
  background: light-dark(#ffffff, #0f172a);
  color: light-dark(#1e293b, #e2e8f0);
}

.card {
  background: light-dark(#f8fafc, #1e293b);
  border: 1px solid light-dark(#e2e8f0, #334155);
  box-shadow: light-dark(
    0 1px 3px rgba(0,0,0,0.1),
    0 1px 3px rgba(0,0,0,0.3)
  );
}

.texte-mute {
  color: light-dark(#64748b, #94a3b8);
}

/* ⚠️ light-dark() ne fonctionne QUE quand
   color-scheme est défini sur un parent ancêtre
   avec "light dark" (ou juste "dark") */

4. Visualisation — Conversion entre formats

CONVERSION ENTRE FORMATS — MÊME COULEUR
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Bleu primaire : #2563eb
  ┌─────────────────────────────────────────┐
  │  HEX    #2563eb                         │
  │  RGB    rgb(37 99 235)                  │
  │  HSL    hsl(217 91% 57%)               │
  │  HWB    hwb(217 15% 8%)                │
  │  OKLCH  oklch(0.62 0.19 250)           │
  │  OKLAB  oklab(0.58 -0.04 -0.12)        │
  │  LAB    lab(47 14 -56)                  │
  └─────────────────────────────────────────┘

  Rouge erreur : #dc2626
  ┌─────────────────────────────────────────┐
  │  HEX    #dc2626                         │
  │  RGB    rgb(220 38 38)                  │
  │  HSL    hsl(0 72% 51%)                 │
  │  OKLCH  oklch(0.60 0.21 25)            │
  └─────────────────────────────────────────┘

La même couleur exprimée dans différents espaces colorimétriques

4.1 La structure d'un espace colorimétrique

MODÈLES DE COULEURS — COMPARAISON
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  RGB/HEX                     HSL
  ┌───────────────┐           ┌───────────────┐
  │ Rouge (0-255) │           │ Teinte (0-360)│
  │ Vert  (0-255) │           │ Saturation %  │
  │ Bleu  (0-255) │           │ Luminosité %  │
  └───────────────┘           └───────────────┘
  → Pas intuitif pour         → Plus intuitif
    varier la lumière          mais pas uniforme

  OKLCH                       HWB
  ┌───────────────┐           ┌───────────────┐
  │ Luminosité    │           │ Teinte (0-360)│
  │  (0-1, unif.) │           │ Blanc %       │
  │ Chroma (0-0.4)│           │ Noir %        │
  │ Teinte (0-360)│           └───────────────┘
  └───────────────┘           → Le modèle le
  → Le modèle idéal            plus proche de
    pour les palettes           la perception
                               humaine

Comparaison des modèles de couleurs CSS

5. Accessibilité et contraste (WCAG)

WCAG (Web Content Accessibility Guidelines) définit des niveaux de contraste entre texte et arrière-plan pour garantir la lisibilité pour tous les utilisateurs, y compris ceux avec des déficiences visuelles.
Niveau Ratio minimum (texte normal) Ratio minimum (texte grand) Description
AA 4.5:1 3:1 Minimum recommandé — obligation légale dans beaucoup de pays
AAA 7:1 4.5:1 Niveau supérieur — recommandé pour un maximum d'accessibilité
✅ Blanc / Noir
Ratio: 15.4:1
✅ Bleu / Blanc
Ratio: 4.6:1
❌ Gris clair / Blanc
Ratio: 2.3:1
❌ Blanc / Gris très clair
Ratio: 1.4:1
/* Bonnes pratiques de contraste */
/* ❌ Texte trop faible sur fond clair */
.mauvais {
  background: #f8fafc;
  color: #cbd5e1;    /* Ratio ~1.5:1 — FAIL */
}

/* ✅ Texte suffisamment contrasté */
.bon {
  background: #f8fafc;
  color: #334155;    /* Ratio ~9.5:1 — PASS AAA */
}

/* ✅ Bonne combinaison sur fond coloré */
.bouton-accessible {
  background: #2563eb;
  color: #ffffff;     /* Ratio ~4.6:1 — PASS AA */
}

/* ✅ Pour le texte secondaire (plus petit) */
.texte-secondaire {
  background: #ffffff;
  color: #475569;    /* Ratio ~7:1 — PASS AAA */
}

/* Outils pour vérifier le contraste :
   - Chrome DevTools → onglet Accessibility → "Contrast"
   - https://webaim.org/resources/contrastchecker/
   - Extension axe DevTools */

6. Dark mode avec CSS

Le dark mode nécessite une double palette de couleurs et un mécanisme pour basculer entre les deux. Le CSS offre deux approches : prefers-color-scheme (automatique) et color-scheme + light-dark() (moderne).

6.1 Approche classique avec media query

/* Mode clair (par défaut) */
:root {
  --bg: #ffffff;
  --bg-card: #f8fafc;
  --texte: #1e293b;
  --texte-muted: #64748b;
  --bordure: #e2e8f0;
  --primaire: #2563eb;
}

/* Mode sombre — bascule automatique */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f172a;
    --bg-card: #1e293b;
    --texte: #e2e8f0;
    --texte-muted: #94a3b8;
    --bordure: #334155;
    --primaire: #60a5fa;
  }
}

/* Utilisation */
body { background: var(--bg); color: var(--texte); }
.card {
  background: var(--bg-card);
  border: 1px solid var(--bordure);
}
a { color: var(--primaire); }

6.2 Approche moderne avec color-scheme + light-dark()

/* Déclarer le support des deux modes */
:root {
  color-scheme: light dark;
}

/* light-dark() remplace toutes les variables ! */
body {
  background: light-dark(#ffffff, #0f172a);
  color: light-dark(#1e293b, #e2e8f0);
}

.card {
  background: light-dark(#f8fafc, #1e293b);
  border: 1px solid light-dark(#e2e8f0, #334155);
}

a {
  color: light-dark(#2563eb, #60a5fa);
}

/* Avantage : pas besoin de variables ni de media query */

6.3 Toggle manuel avec data-attributes

/* Le HTML : <html data-theme="sombre"> */
:root[data-theme="sombre"] {
  --bg: #0f172a;
  --texte: #e2e8f0;
}

:root[data-theme="clair"] {
  --bg: #ffffff;
  --texte: #1e293b;
}

/* Transition fluide entre les modes */
:root {
  transition: background-color 0.3s, color 0.3s;
}

/* JavaScript pour toggle */
<script>
  const toggle = document.getElementById('theme-toggle');
  toggle.addEventListener('click', () => {
    const html = document.documentElement;
    const current = html.getAttribute('data-theme');
    html.setAttribute('data-theme', current === 'sombre' ? 'clair' : 'sombre');
  });
</script>

Mode Clair

background: #ffffff
texte: #1e293b

Mode Sombre

background: #0f172a
texte: #e2e8f0

7. Créer un système de couleurs complet

7.1 Architecture en 3 niveaux

/* ═══════════════════════════════════════════
   NIVEAU 1 — PRIMITIVES (valeurs brutes)
   ═══════════════════════════════════════════ */
:root {
  /* Teintes de base en OKLCH */
  --blue-50:  oklch(0.97 0.02 250);
  --blue-100: oklch(0.93 0.04 250);
  --blue-200: oklch(0.87 0.08 250);
  --blue-300: oklch(0.79 0.12 250);
  --blue-400: oklch(0.70 0.15 250);
  --blue-500: oklch(0.62 0.17 250);
  --blue-600: oklch(0.53 0.15 250);
  --blue-700: oklch(0.44 0.12 250);
  --blue-800: oklch(0.35 0.09 250);
  --blue-900: oklch(0.25 0.06 250);

  --gray-50:  oklch(0.98 0.005 250);
  --gray-100: oklch(0.96 0.005 250);
  --gray-200: oklch(0.92 0.005 250);
  --gray-300: oklch(0.87 0.005 250);
  --gray-400: oklch(0.71 0.01 250);
  --gray-500: oklch(0.55 0.01 250);
  --gray-600: oklch(0.45 0.01 250);
  --gray-700: oklch(0.37 0.01 250);
  --gray-800: oklch(0.27 0.01 250);
  --gray-900: oklch(0.20 0.01 250);

  --red-500: oklch(0.63 0.25 25);
  --green-500: oklch(0.72 0.19 142);
  --yellow-500: oklch(0.90 0.18 95);
}

/* ═══════════════════════════════════════════
   NIVEAU 2 — SÉMANTIQUE (rôle dans l'UI)
   ═══════════════════════════════════════════ */
:root {
  color-scheme: light dark;

  /* Backgrounds */
  --bg-primary: light-dark(#ffffff, #0f172a);
  --bg-secondary: light-dark(var(--gray-50), var(--gray-900));
  --bg-tertiary: light-dark(var(--gray-100), var(--gray-800));

  /* Texte */
  --text-primary: light-dark(var(--gray-900), var(--gray-50));
  --text-secondary: light-dark(var(--gray-600), var(--gray-400));
  --text-muted: light-dark(var(--gray-400), var(--gray-500));

  /* Interactions */
  --interactive: var(--blue-500);
  --interactive-hover: var(--blue-600);
  --interactive-active: var(--blue-700);

  /* États */
  --success: var(--green-500);
  --error: var(--red-500);
  --warning: var(--yellow-500);

  /* Bordures */
  --border: light-dark(var(--gray-200), var(--gray-700));
  --border-subtle: light-dark(var(--gray-100), var(--gray-800));

  /* Ombres */
  --shadow-sm: light-dark(
    0 1px 2px rgba(0,0,0,0.05),
    0 1px 2px rgba(0,0,0,0.2)
  );
  --shadow-md: light-dark(
    0 4px 6px rgba(0,0,0,0.07),
    0 4px 6px rgba(0,0,0,0.3)
  );
}

/* ═══════════════════════════════════════════
   NIVEAU 3 — COMPOSANT (propriétés du composant)
   ═══════════════════════════════════════════ */
.btn {
  --btn-bg: var(--interactive);
  --btn-text: white;
  --btn-radius: 8px;

  background: var(--btn-bg);
  color: var(--btn-text);
  border-radius: var(--btn-radius);
}

.card {
  --card-bg: var(--bg-primary);
  --card-border: var(--border);
  --card-padding: 1.5rem;

  background: var(--card-bg);
  border: 1px solid var(--card-border);
  padding: var(--card-padding);
}
50
100
200
300
400
500
600
700
800
900

8. Erreurs fréquentes

Erreur 1 : Ne pas vérifier le contraste
/* ❌ Texte gris très clair sur fond blanc — illisible */
.pied-de-page {
  background: #ffffff;
  color: #d1d5db;  /* Ratio ~1.6:1 — FAIL AAA et AA */
}

/* ✅ Minimum recommandé : ratio 4.5:1 pour AA */
.pied-de-page {
  background: #ffffff;
  color: #6b7280;  /* Ratio ~4.8:1 — PASS AA */
}

/* Vérification avec Chrome DevTools :
   Onglet Accessibility → section Contrast → ratio affiché */
Erreur 2 : Utiliser des couleurs nommées pour des tokens
/* ❌ "tomato" n'est pas une couleur définie par l'équipe */
.alerte {
  background: tomato;
}

/* ✅ Utiliser des tokens sémantiques */
:root {
  --error-bg: #fef2f2;
  --error-text: #dc2626;
}
.alerte {
  background: var(--error-bg);
  color: var(--error-text);
}

/* Si tu dois utiliser des couleurs nommées, les
   transformer en variables dès le début */
Erreur 3 : Créer des palettes avec HSL et obtenir des résultats incohérents
/* ❌ HSL n'est PAS perceptuellement uniforme */
.bleu-500 { color: hsl(217, 91%, 60%); }  /* Luminosité 60% */
.vert-500 { color: hsl(142, 70%, 45%); }  /* Luminosité 45% */
/* Le vert paraît plus sombre que le bleu malgré la teinte différente,
   mais les luminosités ne sont PAS comparables entre teintes */

/* ✅ Avec OKLCH, la luminosité est toujours comparable */
.bleu-500 { color: oklch(0.62 0.19 250); }  /* L = 0.62 */
.vert-500 { color: oklch(0.62 0.19 142); }  /* L = 0.62 → même luminosité perçue ! */
Erreur 4 : Oublier le fallback pour les couleurs modernes
/* ❌ Les navigateurs anciens ne comprennent pas oklch() */
.bouton {
  background: oklch(0.62 0.19 250);
  /* Firefox < 113, Chrome < 111 : rien ne s'affiche ! */
}

/* ✅ Fallback obligatoire */
.bouton {
  background: #2563eb;                   /* Fallback */
  background: oklch(0.62 0.19 250);     /* Navigateurs modernes */
}

/* ✅ Ou utiliser @supports */
@supports (color: oklch(0 0 0)) {
  .bouton {
    background: oklch(0.62 0.19 250);
  }
}

9. Bonnes pratiques

Guide des couleurs :
  • Utiliser OKLCH pour les palettes de design — c'est le format le plus fiable pour des couleurs harmonieuses.
  • Créer un système en 3 niveaux : primitives → sémantique → composant.
  • Ne jamais utiliser de couleurs en dur dans les propriétés de composants — toujours passer par des variables.
  • Vérifier le contraste WCAG AA minimum pour tout texte lisible.
  • Fournir un fallback pour les couleurs modernes (oklch, light-dark, color-mix).
  • Utiliser color-mix() pour générer des variantes automatiquement.
  • Préférer light-dark() aux media queries pour le dark mode (plus concis).
  • Documenter le système de couleurs dans un fichier dédié (ex: colors.css).
Palette de base recommandée :
  • 3 teintes principales : primaire, secondaire, accent.
  • 1 teinte neutre : gray (de 50 à 900).
  • 3 états : succès (vert), erreur (rouge), avertissement (orange/jaune).
  • Chaque teinte : 9 à 11 nuances (50, 100, 200… 900).
  • Total : ~50 à 70 couleurs uniques pour un design system complet.

10. Mini-défi

Exercice 1 : Palette OKLCH

Crée une palette de 10 nuances (50 à 900) d'une couleur au choix en utilisant uniquement oklch() et des variables CSS. La palette doit être harmonieuse avec une chroma constante.

Exercice 2 : Conversion

Exprime la couleur #dc2626 (rouge d'erreur) dans les 5 formats : HEX, RGB, HSL, HWB et OKLCH. Vérifie que toutes les syntaxes produisent la même couleur visuelle.

Exercice 3 : Contraste WCAG

Vérifie les ratios de contraste de ces combinaisons et classe-les en PASS AA / FAIL AA / PASS AAA / FAIL AAA :

  • Noir (#000000) sur blanc (#ffffff)
  • Bleu (#2563eb) sur blanc (#ffffff)
  • Gris (#94a3b8) sur blanc (#ffffff)
  • Blanc (#ffffff) sur vert (#16a34a)

Exercice 4 : Dark mode

Implémente un dark mode complet avec light-dark() pour un site de 3 pages : un header, un sidebar, un contenu principal. Inclure les états hover et les ombres.

Exercice 5 : Système de couleurs complet

Crée un fichier design-tokens.css avec les 3 niveaux (primitives, sémantiques, composants) pour un site e-commerce : produits, panier, catégories, notifications, etc.

11. Projet d'application

Projet : Thème switcher complet

Crée un système de thèmes CSS complet avec :

/* design-system.css — Système complet */
:root {
  color-scheme: light dark;
}

/* ═══ PRIMITIVES ═══ */
:root {
  /* Teinte bleue — primaire */
  --blue-50:  oklch(0.97 0.02 250);
  --blue-100: oklch(0.93 0.04 250);
  --blue-200: oklch(0.87 0.08 250);
  --blue-500: oklch(0.62 0.17 250);
  --blue-600: oklch(0.53 0.15 250);
  --blue-700: oklch(0.44 0.12 250);

  /* Teinte neutre */
  --gray-50:  oklch(0.98 0.005 250);
  --gray-100: oklch(0.96 0.005 250);
  --gray-200: oklch(0.92 0.005 250);
  --gray-400: oklch(0.71 0.01 250);
  --gray-600: oklch(0.45 0.01 250);
  --gray-800: oklch(0.27 0.01 250);
  --gray-900: oklch(0.20 0.01 250);
  --white: #ffffff;

  /* États */
  --red-500: oklch(0.63 0.25 25);
  --green-500: oklch(0.72 0.19 142);
}

/* ═══ SÉMANTIQUE ═══ */
:root {
  --bg-page: light-dark(var(--white), var(--gray-900));
  --bg-card: light-dark(var(--gray-50), var(--gray-800));
  --text-1: light-dark(var(--gray-900), var(--gray-50));
  --text-2: light-dark(var(--gray-600), var(--gray-400));
  --border-1: light-dark(var(--gray-200), var(--gray-800));
  --accent: var(--blue-500);
}

/* ═══ COMPOSANTS ═══ */
.btn-primary {
  padding: 0.5rem 1.25rem;
  background: var(--accent);
  color: var(--white);
  border: none;
  border-radius: 8px;
  font-weight: 600;
  transition: background 0.15s ease;
}
.btn-primary:hover {
  background: color-mix(in oklch, var(--accent) 85%, black);
}
.btn-primary:active {
  background: color-mix(in oklch, var(--accent) 70%, black);
}

.card {
  background: var(--bg-card);
  border: 1px solid var(--border-1);
  border-radius: 12px;
  padding: 1.5rem;
}

.badge-success {
  background: color-mix(in oklch, var(--green-500) 15%, transparent);
  color: var(--green-500);
  padding: 0.25rem 0.75rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.8rem;
}

Contraintes :

  • Minimum 5 composants stylés (bouton, carte, badge, input, navigation).
  • Dark mode automatique avec light-dark() ET fallback avec prefers-color-scheme.
  • Toutes les couleurs doivent passer WCAG AA (contraste 4.5:1 minimum).
  • Utiliser oklch() pour les primitives et color-mix() pour les hover.
  • Un toggle manuel (bouton) pour switcher entre les modes.

12. Révision

Quiz rapide

  1. Quelle est la différence entre rgb() et hsl() ?
  2. Quel est l'avantage de oklch() par rapport à hsl() ?
  3. Quel est le ratio de contraste minimum WCAG AA pour du texte normal ?
  4. Que fait color-mix(in oklch, #2563eb, white) ?
  5. Comment déclarer le support du dark mode ?
  6. Qu'est-ce que light-dark() et quand l'utiliser ?
  7. Pourquoi faut-il un fallback pour les couleurs modernes ?
  8. Quelle est la bonne syntaxe moderne pour rgba() ?
  9. Combien de couleurs nommées le CSS standard définit-il ?
  10. Quelle est la différence entre currentColor et inherit ?
Réponses :
  1. rgb() utilise rouge-vert-bleu (additif), hsl() utilise teinte-saturation-luminosité (plus intuitif pour varier).
  2. oklch() est perceptuellement uniforme : une luminosité de 0.6 a la même intensité perçue quelle que soit la teinte.
  3. 4.5:1 pour du texte normal (AA), 3:1 pour du texte grand (≥18pt ou 14pt gras).
  4. Il mélange le bleu et le blanc dans l'espace OKLCH, résultant en un bleu clair.
  5. Avec color-scheme: light dark; sur :root.
  6. light-dark(clair, sombre) retourne la bonne couleur selon le mode actif. Plus concis qu'une media query.
  7. Les navigateurs anciens ne supportent pas oklch(), light-dark(), etc. — sans fallback, la propriété est ignorée.
  8. rgb(37 99 235 / 0.5) — espaces entre canaux, / pour l'alpha.
  9. 148 couleurs nommées dans le module CSS Color Level 4.
  10. currentColor = la valeur computed de color de l'élément. inherit = la valeur héritée du parent (peut être différente si une règle s'applique).

13. Mémo rapide (Cheat Sheet)

┌─────────────────────────────────────────────────────────────────────┐
│            CHEAT SHEET — COULEURS CSS                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  FORMATS :                                                          │
│  ────────                                                           │
│  red, blue, tomato      nommées (148 au total)                     │
│  #ff0000  #f00          HEX (6 ou 3 chiffres + alpha optionnel)    │
│  rgb(r g b / a)         rouge-vert-bleu (0-255 ou %)              │
│  hsl(h s% l% / a)       teinte-saturation-luminosité              │
│  hwb(h w% b%)           teindle-blanc-noir                         │
│  oklch(l c h / a)       perceptuellement uniforme (recommandé)     │
│                                                                     │
│  FONCTIONS :                                                        │
│  ──────────                                                         │
│  color-mix(in espace, c1 %, c2 %)   mélanger des couleurs         │
│  light-dark(couleur-claire, sombre)  adaptatif (auto dark mode)    │
│  currentColor             valeur de color de l'élément             │
│  transparent              rgba(0 0 0 / 0)                          │
│  color(display-p3 ...)    gamut plus large (P3)                     │
│                                                                     │
│  ACCESSIBILITÉ :                                                    │
│  ───────────────                                                    │
│  WCAG AA  : ratio 4.5:1 (texte normal) / 3:1 (texte grand)       │
│  WCAG AAA : ratio 7:1 (texte normal) / 4.5:1 (texte grand)       │
│                                                                     │
│  DARK MODE :                                                        │
│  ──────────                                                         │
│  color-scheme: light dark;    déclarer le support                  │
│  @media (prefers-color-scheme: dark)  media query classique        │
│  light-dark(a, b)            fonction moderne (recommandée)        │
│                                                                     │
│  SYSTÈME DE COULEURS :                                              │
│  ─────────────────────                                              │
│  Niveau 1 : Primitives (valeurs brutes en oklch)                   │
│  Niveau 2 : Sémantiques (--bg-primary, --text-secondary)           │
│  Niveau 3 : Composants (--btn-bg, --card-border)                   │
│                                                                     │
│  BONNES PRATIQUES :                                                 │
│  ─────────────────                                                  │
│  1. oklch() pour les palettes                                       │
│  2. color-mix() pour les variantes                                  │
│  3. light-dark() pour le dark mode                                 │
│  4. Toujours un fallback pour les couleurs modernes                 │
│  5. Vérifier le contraste WCAG AA                                   │
│  6. Variables pour toutes les couleurs utilisées                    │
│  7. 3 niveaux : primitives → sémantique → composant                │
└─────────────────────────────────────────────────────────────────────┘

Résumé complet de toutes les notions sur les couleurs CSS