Vos docs paraissent « correctes » jusqu’à ce qu’un vrai utilisateur arrive avec une vraie configuration : mode sombre activé, mouvement réduit, écran OLED
et niveau de zoom du navigateur que vous n’avez pas testé. Alors les blocs de code brillent comme un arc de soudure, les états au survol de la barre latérale disparaissent,
et l’animation de défilement fluide continue comme si elle voulait gagner un marathon.
Les thèmes échouent de façons ennuyeuses : couleurs incohérentes, contraste illisible, mise en page qui saute, et CSS « one-off » qui devient une décharge.
Les design tokens — mis en œuvre avec des variables CSS et une stratégie sensée pour le mode sombre et le mouvement réduit — sont ce qui permet de garder un site de documentation
ennuyeux en production. L’ennui, c’est bien.
Ce que sont réellement les design tokens (et ce qu’ils ne sont pas)
Un design token est une décision nommée. Pas une couleur. Pas une police. Pas « #1d9bf0 ».
Une décision : « c’est la couleur d’accentuation » ou « c’est la couleur de l’anneau de focus » ou « c’est l’espacement entre paragraphes empilés ». Les tokens vous permettent de parler
de décisions d’une manière qui survit aux refontes, au mode sombre et à trois frameworks CSS différents essayant d’occuper le même dépôt.
Couches de tokens : ne sautez pas ceci sinon vous le regretterez
Si vous aplatissez tout en un tas de variables, vous créez un thème qui ne peut pas évoluer. Vous voulez des couches :
- Tokens de base : primitives brutes comme les couleurs (dans un espace perceptuel si possible), familles de polices, pas d’espacement.
- Tokens sémantiques : noms basés sur l’intention comme
--color-bg,--color-fg,--color-accent. - Tokens de composant : seulement si nécessaire, par exemple
--codeblock-bgou--sidebar-hover-bg.
Les tokens de base peuvent changer lors d’un rebranding. Les tokens sémantiques doivent rester majoritairement stables. Les tokens de composant sont
une soupape de dérogation contrôlée — utilisez-les parcimonieusement et seulement quand les tokens sémantiques ne peuvent pas exprimer les contraintes d’un composant.
Ce que les tokens ne sont pas
- Ce n’est pas un dépotoir pour chaque valeur hex aléatoire copiée depuis une maquette.
- Ce n’est pas un remplacement des primitives de mise en page et d’un design de composant sensé.
- Ce n’est pas une licence pour inventer des noms mignons comme
--blueberry-muffin. Vous ne gérez pas une boutique de glaces.
Un heuristique fiable : si un nom de variable n’aiderait pas quelqu’un à déboguer un problème de contraste à 2 h du matin, ce n’est pas un token,
c’est un secret.
Faits et contexte historique importants en 2025
Les thèmes et les tokens semblent tendance. Ils le sont, mais ils sont aussi le point de convergence de quelques décennies d’histoire du CSS,
de travail sur l’accessibilité et de conventions de plateforme. Voici des faits concrets qui influencent les thèmes de docs d’aujourd’hui :
- Les propriétés personnalisées CSS (variables) sont largement disponibles depuis environ 2017. C’est assez ancien pour être fiable en production, assez récent pour que certaines équipes les évitent par habitude.
prefers-color-schemeest devenu utilisable partout autour de 2020–2021, transformant le mode sombre d’un « fichier CSS supplémentaire » en un signal de préférence utilisateur reconnu.prefers-reduced-motionest une media query née des réglages d’accessibilité du système ; l’ignorer équivaut à ignorer « je souffre du mal de mer ». Les utilisateurs le remarquent.- Les recommandations de contraste WCAG (notamment 2.1 et suivantes) ont poussé les équipes hors du « ça a l’air bien sur mon laptop » vers une lisibilité mesurable pour le texte normal et le texte large.
- L’adoption des écrans OLED a rendu les fonds purement noirs plus courants — mais a aussi rendu le texte trop lumineux et les accents saturés plus agressifs. « Mode sombre » n’est pas « #000 partout ».
- La coloration syntaxique pour les blocs de code est désormais une surface de lisibilité majeure. Ce n’est pas décoratif ; c’est littéralement la façon dont vos docs communiquent. De mauvais tokens ici fatiguent les utilisateurs sans bruit.
- Les efforts de standardisation des design tokens (formats communautaires et toolchains) ont normalisé l’idée des tokens comme un artefact de pipeline, pas juste des variables CSS dans un fichier.
- Les conventions d’interface système ont appris aux utilisateurs à s’attendre à ce que le choix de thème soit mémorisé par site, mais à suivre par défaut la préférence système. Si vous luttez contre ça, vous perdez. Silencieusement, mais vous perdez.
Ce ne sont pas des anecdotes. C’est pourquoi l’approche « choisis juste quelques couleurs » meurt dès que vos docs deviennent populaires.
Un modèle de tokens qui ne s’effondrera pas plus tard
Les thèmes de docs ont un problème spécial : ils sont majoritairement typographie et densité de contenu, avec de petites interactions
(nav, recherche, boutons de copie de code). Cela pousse les équipes à sous-concevoir les tokens. Puis la première demande de changement « mineure »
arrive — nouveaux types d’encarts, badges de méthode d’API, un thème de syntaxe différent — et soudain vous déboguez pourquoi #fff
est utilisé 46 fois dans 12 fichiers.
Commencez par les contraintes : les docs ne sont pas un site marketing
Votre thème de docs doit optimiser pour :
- La lisibilité sur de longues sessions de lecture.
- La cohérence entre les types de contenus (Markdown, tableaux, code, diagrammes).
- Des interactions prévisibles (états de focus, états au survol, navigation au clavier).
- Un faible risque de régression lorsque vous changez des tokens.
Votre thème de docs ne doit pas optimiser pour :
- La saturation maximale de la marque sur chaque pixel.
- Des animations originales.
- Du « delight » qui casse le défilement ou déclenche la sensibilité au mouvement.
Nommage de tokens opiniâtre
Utilisez un schéma de noms qui encode l’intention et l’échelle. Par exemple :
--space-1,--space-2,--space-3… pour les pas d’espacement (tokens de base).--radius-1,--radius-2… pour le rayon des coins.--color-neutral-0…--color-neutral-100pour une rampe de neutres (tokens de base).--color-bg,--color-fg,--color-muted,--color-border(tokens sémantiques).--color-link,--color-link-hover,--color-focus-ring(tokens sémantiques, toujours basés sur l’intention).
Évitez d’attacher les tokens sémantiques à des noms de marque : --color-twitter-blue sera un ticket de bug futur.
La marque changera ou le contexte évoluera, et le nom de votre token mentira.
Nombre de tokens : moins que vous ne pensez, plus que vous ne voulez
Si vous définissez 300 tokens le premier jour, vous ne construisez pas un thème — vous vous construisez un deuxième travail.
Si vous définissez 12 tokens, vous construisez un piège.
Un point de départ pratique pour un thème de docs :
- Rampe de neutres : 10–14 étapes.
- Accent + états : accent, accent-hover, accent-subtil, anneau de focus.
- Couleurs d’état : success/warn/error/info avec deux pas chacune (plein + fond subtil).
- Typographie : 2 familles de polices (ui + mono), 1–2 tokens de hauteur de ligne, étapes d’échelle pour la taille de police.
- Espacements + rayons : 6–8 pas chacun.
C’est suffisant pour thématiser tout le site sans transformer votre CSS en danse interprétative.
Variables CSS en production : mécanique et arêtes vives
Les propriétés personnalisées CSS sont des variables résolues à l’exécution. C’est la fonctionnalité et le piège. Elles héritent, peuvent être
surchargées et participent à la cascade. Cela les rend parfaites pour les thèmes.
Utilisez la cascade volontairement
La cascade n’est pas le chaos. C’est un plan de contrôle. Votre site de docs devrait définir les tokens à :
:rootpour les valeurs par défaut.[data-theme="dark"]pour les overrides du mode sombre.- Optionnel : des scopes de composants comme
.codeblockuniquement pour les tokens de composant.
Ne définissez pas des tokens à des niveaux imbriqués aléatoires sauf si vous les scopez intentionnellement. Sinon vous obtiendrez des bugs « ça marche sur une page »
parce qu’un conteneur a changé un token et l’enfant l’a hérité.
Privilégiez les tokens sémantiques pour le style des composants
Un composant devrait majoritairement référencer des tokens sémantiques. Exemple :
Le bloc de code devrait utiliser --color-bg-elevated et --color-fg, pas --color-neutral-95.
Si vous codifiez des pas de la rampe de base dans les composants, vous ne pourrez pas retuner le contraste plus tard sans toucher au CSS des composants.
Performance : les variables ne sont pas votre goulot d’étranglement jusqu’à ce qu’elles le deviennent
La plupart des thèmes n’atteignent pas des limites de performance dues uniquement aux variables. Mais vous pouvez créer des problèmes :
- Animer une variable qui affecte la mise en page ou des propriétés lourdes en peinture sur toute la page.
- Surutiliser
filter,backdrop-filterou d’énormes box-shadows lors du basculement de thèmes. - Déclencher des reflows coûteux en changeant le thème sur la racine pour chaque petite interaction.
Gardez les basculements de thème peu fréquents (action utilisateur, pas survol). Gardez les transitions subtiles et bornées.
Une citation à retenir
“L’espoir n’est pas une stratégie.” — General Gordon R. Sullivan
La justesse du thème n’est pas une activité fondée sur l’ambiance. Mesurez le contraste, testez le mouvement réduit et exécutez des contrôles de régression.
Mode sombre « façon X » : contraste élevé, faible dramatisme, pas noir complet
Les gens disent « mode sombre façon X » parce que c’est lisible, net et que ça ne ressemble pas à un cockpit de science-fiction.
Il tend à utiliser un fond presque noir (pas noir pur), des surfaces légèrement élevées et un texte lumineux mais contrôlé.
La clé est la rampe de neutres et la manière dont vous l’allouez aux surfaces.
Pourquoi le presque-noir bat le noir pur pour les docs
Le noir pur (#000) maximise le contraste, ce qui semble bien jusqu’à ce que vous lisiez pendant 40 minutes. Beaucoup d’utilisateurs signalent
un halo (bords lumineux) avec du texte brillant sur du noir pur. Le presque-noir réduit l’éblouissement tout en restant « sombre ».
Aussi : tous les écrans ne se comportent pas pareil. Certains moniteurs écrasent les ombres, certains téléphones augmentent le contraste, et certains navigateurs
appliquent la gestion des couleurs différemment. Le presque-noir vous donne de la marge pour créer de l’élévation et des bordures sans dépendre de valeurs invisibles.
Définir les surfaces : base, élevée, en retrait
Les thèmes de docs ont besoin de tokens de surface. Si vous n’avez qu’un seul token de fond, vous finirez par inventer des gris ad hoc.
Utilisez un petit ensemble de surfaces :
--color-bgpour la base de la page.--color-bg-elevatedpour la navigation, les panneaux, les cartes.--color-bg-insetpour les blocs de code, les encarts et les conteneurs en retrait.
Rendez les bordures réelles en mode sombre
En mode clair vous pouvez vous permettre des bordures subtiles. En mode sombre, les bordures disparaissent ou deviennent des contours néon.
Tokenisez les bordures par intention :
--color-borderpour les traits par défaut.--color-border-strongpour les séparateurs et les lignes de grille des tableaux.
Si vous utilisez une seule couleur de bordure, tableaux et barres latérales se fondront en une pâte indistincte, surtout pour les utilisateurs à perception de contraste réduite.
Liens et accents : l’échec « trop bleu »
Les thèmes façon X utilisent un accent saturé, mais ils contrôlent où il apparaît. Vos docs devraient faire de même :
- Liens : couleur d’accent, mais évitez des soulignements trop fins sur fonds sombres.
- Boutons : fond en accent avec texte lisible, mais gardez les états hover dans un petit delta.
- Anneaux de focus : ne réutilisez pas l’accent sans réflexion ; choisissez une couleur de ring visible à la fois en clair et en sombre.
Blague n°1 : le mode sombre n’est pas « rendre tout noir ». Ce n’est pas du theming ; c’est une panne de courant avec de la typographie.
Coloration syntaxique : ne la laissez pas se greffer gratuitement
Les blocs de code sont l’endroit où la plupart des thèmes sombres échouent silencieusement. Le fond est sombre, puis les tokens utilisent des couleurs saturées qui
vibrent, et les yeux de l’utilisateur se mettent en grève. Tokenisez les couleurs de syntaxe séparément et gardez-les dans une palette contrôlée.
Règle pratique : gardez les couleurs de syntaxe moins saturées que l’accent, et assurez-vous que les commentaires sont lisibles sans dominer.
Si la couleur des commentaires est trop faible, on ne distingue pas code et annotation ; si elle est trop brillante, elle devient du bruit visuel.
Mouvement réduit : le contrat que vous violez déjà
Le mouvement réduit n’est pas « agréable à avoir ». C’est une préférence utilisateur explicite. Quand un utilisateur active le mouvement réduit, il vous dit que l’animation peut provoquer inconfort ou nausée.
Si votre site de docs défile encore en douceur, fait des fondus enchaînés, des parallaxes de fond ou anime de grandes transformations, vous violez le contrat.
Ce qu’il faut désactiver (et ce qu’il faut garder)
Sous prefers-reduced-motion: reduce :
- Désactiver le défilement fluide, les effets de parallaxe, les carrousels auto-advancés, les dégradés d’arrière-plan animés.
- Réduire les grandes transitions de transform (entrées de barre latérale), les longs fondus et les mises en évidence animées.
- Conserver de courtes micro-transitions non essentielles si elles ne créent pas de mouvement à l’échelle de la fenêtre (p. ex. changements de couleur 100ms). Mais envisagez de les désactiver aussi pour simplifier.
Le comportement de défilement est le piège classique
Beaucoup de sites de docs définissent html { scroll-behavior: smooth; } parce que ça a l’air « fini ».
Sous mouvement réduit, c’est l’inverse. Vos tokens et votre architecture CSS devraient permettre de l’éteindre proprement.
Tokens d’animation : oui, tokeniser le mouvement en vaut la peine
Créez des tokens de mouvement :
--motion-duration-fast,--motion-duration-medium--motion-ease-standard--motion-enabledcomme interrupteur conceptuel (implémenté via overrides de media query)
Puis, sous mouvement réduit, réglez les durées presque à zéro. Ne comptez pas sur l’audit manuel de chaque ligne de transition.
Vous en oublierez une. Vous en oubliez toujours une.
Plan d’implémentation : tokens, couches et overrides
Structure CSS : séparer les tokens du CSS des composants
Placez les tokens dans un seul fichier (ou un bundle généré) chargé tôt. Ensuite, construisez des composants qui consomment les tokens.
L’anti-pattern est de mêler les tokens aux fichiers de composants, car cela rend la surface de tokens non révisable.
Une disposition de tokens pratique
Fichiers recommandés :
tokens.css: tokens de base + sémantiques, clair et sombre.components.css: composants qui référencent des tokens sémantiques.overrides.css: corrections rares par page ou par intégration ; traitez-le comme radioactif.
Contrat de basculement de thème
Prenez en charge ces modes :
- Système (par défaut) : suivre
prefers-color-scheme. - Clair (surcharge utilisateur) : forcer le clair quel que soit le système.
- Sombre (surcharge utilisateur) : forcer le sombre quel que soit le système.
Implémentez avec un attribut data-theme sur html ou body, plus un état « système » où l’attribut est absent.
Ne faites pas à la fois attribut et classes venant de frameworks différents ; vous créerez des sélecteurs conflictuels et passerez une après-midi à perdre contre la spécificité.
Contrat mouvement réduit
Utilisez des media queries, pas des hacks côté agent utilisateur :
@media (prefers-reduced-motion: reduce) { ... }
Évitez d’utiliser du JS pour « détecter » le mouvement réduit sauf si vous devez absolument. Le CSS est plus fiable et ne dépend pas du timing d’exécution du script.
Exemple : fichier de tokens (conceptuel)
Je ne vais pas vous noyer dans un dump complet de CSS de thème, mais voici le schéma : rampes de base, puis mapping sémantique, puis overrides sombres.
Gardez vos tokens serrés et lisibles.
Outils et pipelines : tenir les humains hors du chemin chaud
Le theming en production ressemble au stockage en production : vos échecs sont généralement banals et auto-infligés. Les outils aident, mais seulement si vous les traitez
comme des garde-fous plutôt que comme une baguette magique.
Linting et contrôles de cohérence
Utilisez un linter de style pour détecter :
- Les couleurs codées en dur dans le CSS des composants (quand vous exigez des tokens).
- Les références de variables invalides.
- Les sélecteurs trop spécifiques qui rendent les overrides de tokens impossibles.
Tests de contraste comme signal de build
Ne publiez pas un changement de thème sans vérifier le contraste pour :
- Le texte du corps sur le fond
- Les liens sur le fond
- Le texte de code sur le fond du code
- Le texte et les couleurs de bordure « muted » (souvent les premiers à échouer en mode sombre)
Vous n’avez pas besoin de perfection. Vous avez besoin d’une politique cohérente et d’un moyen de bloquer les régressions évidentes.
Tests de régression visuelle : assurance pas chère
Pour les sites de docs, la régression visuelle est disproportionnellement efficace parce que les pages sont templatisées.
Capturez un petit ensemble de pages canoniques :
- Page d’accueil / landing
- Page de référence API avec tableaux
- Page tutoriel avec encarts
- Vue de résultats de recherche
- Page avec longs blocs de code
Exécutez-les en clair et en sombre, et avec mouvement réduit. Oui, le mouvement réduit affecte les captures si vous avez des animations susceptibles d’être capturées en milieu de transition. C’est le but : attraper la nondéterminisme.
Deux blagues sur le thème, dose maximale sûre
Blague n°2 : si vous pensez ne pas avoir besoin de tokens, vous n’avez jamais rencontré « juste ce bleu spécial » lors d’un rebranding trimestriel.
Tâches pratiques : commandes, sorties et décisions (12+)
Ce sont le genre de vérifications que vous exécutez lorsqu’un changement de thème est sur le point d’être publié, ou quand quelque chose « ne va pas » et que vous voulez
trouver la cause réelle. Chaque tâche inclut : la commande, ce que signifie la sortie, et la décision que vous prenez.
Supposons un dépôt avec un site construit sous dist/ et du CSS source sous src/.
Tâche 1 : Trouver les couleurs hex codées en dur qui contournent les tokens
cr0x@server:~$ rg -n --hidden --glob '!dist/**' -e '#[0-9a-fA-F]{3,8}\b' src
src/components/sidebar.css:42: border-left: 1px solid #2f3336;
src/pages/api.css:118: color: #1d9bf0;
Signification de la sortie : Vous avez des couleurs littérales dans le CSS de composants/pages.
Décision : Remplacez par des tokens sémantiques (p. ex. --color-border, --color-link) ou justifiez pourquoi un token de composant est requis.
Tâche 2 : Trouver les littéraux rgb()/hsl() (contournent aussi les tokens)
cr0x@server:~$ rg -n --hidden --glob '!dist/**' -e '\brgb(a)?\(' -e '\bhsl(a)?\(' src
src/components/callout.css:9: background: rgba(29, 155, 240, 0.12);
Signification de la sortie : Des calculs de couleur sont intégrés dans les composants.
Décision : Déplacez les valeurs calculées dans des tokens (p. ex. --color-accent-subtle-bg) afin que le mode sombre puisse override correctement.
Tâche 3 : Énumérer les variables CSS définies dans les tokens
cr0x@server:~$ rg -n '^\s*--[a-z0-9-]+\s*:' src/tokens.css | head
12: --space-1: 0.25rem;
13: --space-2: 0.5rem;
14: --radius-1: 6px;
15: --color-bg: #ffffff;
16: --color-fg: #0f1419;
Signification de la sortie : Vue rapide des définitions de tokens.
Décision : Confirmez la cohérence des noms et que des tokens sémantiques existent pour chaque surface UI majeure (bg/fg/border/link/focus).
Tâche 4 : Détecter les variables utilisées mais jamais définies (typos et tokens morts)
cr0x@server:~$ python3 - <<'PY'
import re, pathlib
root = pathlib.Path("src")
defs=set()
uses=set()
for p in root.rglob("*.css"):
t=p.read_text(errors="ignore")
for m in re.finditer(r'--[a-z0-9-]+(?=\s*:)', t): defs.add(m.group(0))
for m in re.finditer(r'var\(\s*(--[a-z0-9-]+)', t): uses.add(m.group(1))
missing=sorted(uses-defs)
print("\n".join(missing[:50]))
print(f"\nmissing_count={len(missing)}")
PY
--color-codblock-bg
--motion-duration-fst
missing_count=2
Signification de la sortie : Des tokens référencés dans le CSS ne sont pas définis ; ce sont probablement des fautes de frappe.
Décision : Corrigez l’orthographe, ou définissez le token intentionnellement. C’est une source classique de régressions « fonctionne en mode clair mais pas en mode sombre ».
Tâche 5 : Trouver où data-theme est appliqué dans le HTML construit
cr0x@server:~$ rg -n 'data-theme=' dist/**/*.html | head
dist/index.html:2:<html lang="en" data-theme="dark">
Signification de la sortie : Votre build codifie un thème.
Décision : Décidez si c’est intentionnel (p. ex. aperçu de docs) ou un bug. La plupart des sites en production devraient
par défaut suivre la préférence système sauf si un réglage utilisateur est stocké.
Tâche 6 : Vérifier que des règles de mouvement réduit existent
cr0x@server:~$ rg -n 'prefers-reduced-motion' src/**/*.css
src/tokens.css:148:@media (prefers-reduced-motion: reduce) {
src/components/search.css:77:@media (prefers-reduced-motion: reduce) {
Signification de la sortie : Vous avez une gestion explicite du mouvement réduit.
Décision : Assurez-vous que cela désactive réellement le défilement fluide et les transitions majeures (pas seulement « duration: 0 » dans un composant).
Tâche 7 : Détecter le défilement fluide global (souvent erroné pour le mouvement réduit)
cr0x@server:~$ rg -n 'scroll-behavior\s*:\s*smooth' src/**/*.css
src/base.css:3:html { scroll-behavior: smooth; }
Signification de la sortie : Le défilement fluide global est activé.
Décision : Ajoutez un override pour le mouvement réduit : sous prefers-reduced-motion: reduce, définissez scroll-behavior: auto.
Tâche 8 : Vérifier les « transition: all » (odeur de performance et d’accessibilité)
cr0x@server:~$ rg -n 'transition\s*:\s*all\b' src/**/*.css
src/components/tabs.css:21: transition: all 250ms ease;
Signification de la sortie : Vous animez tout, y compris des propriétés qui causent des remises en page/peinture coûteuses.
Décision : Remplacez par des propriétés explicites (p. ex. color, background-color, opacity) et raccourcissez la durée ; désactivez sous mouvement réduit.
Tâche 9 : Vérifier la taille du bundle CSS et sa croissance dans le temps
cr0x@server:~$ ls -lh dist/assets/*.css
-rw-r--r-- 1 cr0x cr0x 184K Dec 29 10:11 dist/assets/site.css
-rw-r--r-- 1 cr0x cr0x 62K Dec 29 10:11 dist/assets/vendor.css
Signification de la sortie : Les tailles de bundle sont visibles et mesurables.
Décision : Si votre CSS gonfle release après release, suspectez un « contournement de tokens » et duplication de composants. Décidez de dédupliquer, scinder ou faire respecter l’usage des tokens.
Tâche 10 : Inspecter les valeurs calculées dans un navigateur headless (sombre vs clair)
cr0x@server:~$ node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('file://' + process.cwd() + '/dist/index.html');
const bg = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--color-bg').trim());
const fg = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--color-fg').trim());
console.log({bg, fg});
await browser.close();
})();
NODE
{ bg: '#0b0f14', fg: '#e7e9ea' }
Signification de la sortie : Les tokens se résolvent en valeurs concrètes à l’exécution.
Décision : Comparez les sorties pour clair et sombre, et vérifiez que les tokens sémantiques changent tandis que le CSS des composants reste stable.
Tâche 11 : Confirmer que le site respecte le schéma de couleurs système sans forcer
cr0x@server:~$ node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ colorScheme: 'dark' });
await page.goto('file://' + process.cwd() + '/dist/index.html');
const attr = await page.evaluate(() => document.documentElement.getAttribute('data-theme'));
const bg = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--color-bg').trim());
console.log({dataTheme: attr, bg});
await browser.close();
})();
NODE
{ dataTheme: null, bg: '#0b0f14' }
Signification de la sortie : La page suit la préférence système (sombre) sans override explicite d’attribut.
Décision : Conservez ce comportement sauf si les exigences produit demandent un défaut forcé. « Système par défaut » réduit la friction utilisateur.
Tâche 12 : Trouver l’usage de !important qui peut casser les overrides de tokens
cr0x@server:~$ rg -n '!\s*important' src/**/*.css
src/components/navbar.css:55: background: var(--color-bg-elevated) !important;
Signification de la sortie : Escalade de spécificité présente.
Décision : Retirez !important sauf si vous luttez délibérément contre du CSS tiers. Si vous devez le garder, isolez-le dans une couche d’intégration afin que les tokens noyau restent overrideables.
Tâche 13 : Valider que l’override mouvement réduit change réellement la durée de transition calculée
cr0x@server:~$ node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ reducedMotion: 'reduce' });
await page.goto('file://' + process.cwd() + '/dist/index.html');
const dur = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--motion-duration-medium').trim());
console.log({motionDurationMedium: dur});
await browser.close();
})();
NODE
{ motionDurationMedium: '1ms' }
Signification de la sortie : Vos tokens de mouvement sont overrideés pour le mouvement réduit.
Décision : Si cela reste à quelque chose comme 250ms, votre CSS pour le mouvement réduit est manquant ou ne charge pas assez tôt.
Tâche 14 : Vérifier le layout shift causé par le chargement des polices (les sites de docs y sont sensibles)
cr0x@server:~$ rg -n 'font-display' src/**/*.css src/**/*.scss
src/fonts.css:4: font-display: swap;
Signification de la sortie : Les polices sont configurées pour swap, réduisant le temps de « texte invisible » mais pouvant causer un léger shift.
Décision : Pour les docs, swap est généralement le bon choix ; si vous voyez des sauts disgracieux, ajustez les métriques de police de secours ou envisagez optional selon les objectifs UX.
Mode d’intervention rapide
Quand un thème de docs « ne va pas », l’astuce est d’éviter de débattre du goût et d’isoler le goulot : contraste, mapping des tokens, comportement du mouvement ou conflits de cascade. Voici l’ordre qui vous amène rapidement aux réponses.
Première étape : vérifier l’état du thème et la cascade
- Le site suit-il la préférence système ou force-t-il un thème via
data-theme? - Les fichiers de tokens sont-ils chargés avant le CSS des composants ?
- Y a-t-il des règles
!importantou des resets de framework qui écrasent les tokens ?
Pourquoi en premier : si la cascade est mauvaise, tout le reste est du bruit. Vous ne pouvez pas déboguer le contraste si le mauvais thème est appliqué.
Deuxième étape : valider que les tokens sémantiques se résolvent en valeurs sensées
- Vérifiez les calculées
--color-bg,--color-fg,--color-link,--color-border. - Confirmez que le mode sombre change les tokens sémantiques, pas le CSS des composants.
Pourquoi en second : les tokens sémantiques sont votre contrat. S’ils sont incohérents, les composants ne seront jamais cohérents.
Troisième étape : signaux d’accessibilité — mouvement réduit et contraste
- Sous mouvement réduit : le défilement fluide est-il désactivé et les transitions majeures proches de zéro ?
- Le focus est-il visible en navigation clavier dans les deux thèmes ?
- Spot-check du contraste sur le texte du corps, les liens, les blocs de code, les encarts et les tableaux.
Pourquoi en troisième : ce sont des échecs impactant les utilisateurs qui peuvent persister des mois sans être remarqués. Ils n’apparaissent pas toujours dans les tests happy-path.
Quatrième étape : performance et déterminisme
- Cherchez
transition: all, de grosses ombres, des filtres et des propriétés de mise en page animées. - Confirmez que les snapshots de régression visuelle sont stables (pas de captures en plein milieu d’une transition).
Pourquoi en quatrième : les problèmes de performance du thème sont généralement auto-infligés et évidents une fois que vous savez où regarder.
Erreurs courantes : symptômes → cause racine → correction
1) « Le mode sombre paraît délavé, mais seulement sur certaines pages »
Symptôme : La plupart des pages vont bien ; quelques-unes ont du gris sur gris ou des encarts illisibles.
Cause racine : Des conteneurs imbriqués overrident un token sémantique (p. ex. --color-fg) ou un composant utilise directement des pas de la rampe de base.
Correction : Restreindre les overrides de tokens aux sélecteurs root du thème ; refactorer les composants pour ne consommer que des tokens sémantiques.
2) « Les liens sont invisibles en mode sombre »
Symptôme : Les liens ressemblent au texte du corps sauf au survol.
Cause racine : Le token de lien est trop proche du token de premier plan ; le token hover repose sur une augmentation de luminosité qui ne fonctionne pas sur des fonds quasi-noirs.
Correction : Augmentez la séparation de teinte et/ou épaississez le soulignement ; définissez --color-link et --color-link-hover explicitement par thème.
3) « L’anneau de focus disparaît sur les blocs de code et boutons »
Symptôme : Les utilisateurs clavier ne voient pas le focus sur certains composants.
Cause racine : Le token de ring réutilise l’accent qui se fond dans les fonds ; ou les styles de focus utilisent outline: none sans remplacement.
Correction : Créez --color-focus-ring avec une haute visibilité dans les deux thèmes ; interdisez outline: none sauf si une meilleure alternative est ajoutée.
4) « Le basculement de thème provoque un flash ou un clignotement »
Symptôme : Le changement de thème provoque un flash blanc ou une palette en état intermédiaire.
Cause racine : Le fichier de tokens se charge tard, ou le JS applique data-theme après le premier paint.
Correction : Inline un petit script d’initialisation de thème dans le head pour définir data-theme avant l’évaluation du CSS, ou évitez de forcer un thème par défaut ; assurez-vous que le CSS des tokens est chargé dans le chemin critique.
5) « Le mouvement réduit est activé mais le défilement s’anime toujours »
Symptôme : L’utilisateur signale un inconfort lié au mouvement ; le dev dit « on supporte le mouvement réduit ».
Cause racine : Le scroll-behavior: smooth global n’est pas overridé sous mouvement réduit ; une librairie JS de smooth-scroll ignore la préférence.
Correction : Ajoutez @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } } ; gatez les animations JS derrière des vérifications de préférence.
6) « Les tableaux sont illisibles en mode sombre »
Symptôme : Les lignes de grille disparaissent ; le fond des lignes alternées ne diffère pas assez.
Cause racine : Un seul token de bordure est utilisé partout ; le striping des lignes utilise des overlays alpha qui s’effondrent sur des fonds quasi-noirs.
Correction : Ajoutez --color-border-strong et des tokens explicites de fond de ligne de tableau par thème.
7) « Les blocs de code ressemblent à une boîte de nuit »
Symptôme : Les couleurs de syntaxe sont douloureusement saturées, les commentaires trop faibles, ou la couleur de sélection illisible.
Cause racine : La palette de syntaxe n’est pas tokenisée ; copiée depuis un autre fond ; la couleur de sélection laissée par défaut du navigateur.
Correction : Définissez des tokens de syntaxe (--syntax-keyword, --syntax-string, etc.) et des tokens de sélection ; validez le contraste avec le fond du code.
8) « Tout est maintenant un token, et personne ne peut rien changer »
Symptôme : Les ingénieurs se plaignent qu’un changement de composant nécessite d’éditer les fichiers de tokens et d’attendre la revue design.
Cause racine : Les tokens incluent des détails de layout spécifiques au composant et des micro-décisions ; la couche sémantique est gonflée.
Correction : Replacez les détails de composant dans le CSS du composant ; gardez les tokens pour les décisions transversales (couleurs, typographie, échelle d’espacement, échelle de mouvement).
Trois mini-histoires d’entreprise depuis les tranchées du theming
Incident : une mauvaise hypothèse sur le « mode sombre système »
Une entreprise moyenne a déployé un portail de docs rafraîchi. L’équipe avait un toggle de thème, un fichier de tokens propre et un comportement « par défaut système ».
En staging, tout avait l’air bien. Ils ont publié un mardi parce que c’est quand tout le monde se sent courageux.
En quelques heures, les tickets de support ont afflué : « Les docs clignotent en blanc quand je les ouvre. » La première hypothèse de l’équipe fut le cache.
Deuxième hypothèse : le CDN. Troisième hypothèse : « les utilisateurs doivent exagérer ». Cette dernière n’a pas bien résisté.
La cause racine était une mauvaise hypothèse : ils supposaient que prefers-color-scheme serait toujours disponible et stable au premier paint.
Mais leur implémentation forçait un thème via du JS après le chargement pour appliquer la préférence sauvegardée. Si le script se chargeait tard (appareil lent, chaîne de scripts tiers bloquée, proxy d’entreprise strict),
la page rendait en clair d’abord, puis basculait en sombre. Flash. Douleur.
La correction n’a pas été glamour. Ils ont inliné un petit script d’initialisation de thème dans le head pour définir data-theme avant l’évaluation du CSS, et ont fait du mode « système » le défaut sans JS.
Résultat : plus de flash, moins de tickets, et une équipe qui a arrêté de traiter le CSS comme « de la magie frontend ».
Optimisation qui a mal tourné : calculs de tokens partout
Une autre organisation a voulu être maligne : un token d’accent unique et tout le reste calculé à partir de lui avec color-mix() et des overlays alpha.
En théorie : moins de tokens, plus de cohérence, rebrands plus faciles.
En pratique : un déraillement au ralenti de différences entre navigateurs et des fonds subtils illisibles.
Le premier problème a été la prévisibilité. Différents navigateurs et espaces colorimétriques produisaient des résultats légèrement différents.
Sur un fond sombre, un overlay d’accent à 12 % semblait correct dans un navigateur, boueux dans un autre, et presque invisible en modes haut contraste.
Le deuxième problème était le contrôle. Quand le design voulait que les fonds d’encart soient plus calmes en mode sombre, l’équipe devait ajuster la formule,
ce qui modifiait tout le reste aussi.
Le système est aussi devenu difficile à déboguer. Quand quelqu’un demandait « quelle est la couleur de ce fond », la réponse était « ça dépend ». C’est une réponse amusante pour un atelier de design et une mauvaise réponse pour une rotation on-call.
Ils ont finalement fait marche arrière vers des tokens sémantiques explicites pour les surfaces et états clés, ne gardant le calcul que là où c’était sûr et non critique.
Le nombre de tokens a augmenté. Les incidents ont diminué. C’est un compromis que l’on fait à chaque fois.
Pratique mais correcte qui a sauvé la mise : pages canoniques et diff visuel
Une troisième société gérait un site de docs avec plusieurs lignes produit. Le thème devait prendre en charge de longs tableaux, diagrammes intégrés
et des exemples de code en trois langages. Ils n’étaient pas spéciaux. Ils étaient juste disciplinés.
Ils ont gardé un petit ensemble de pages canoniques dans le dépôt : une page pour chaque motif de contenu problématique. Chaque changement de thème
exécutait des diffs de captures en clair, sombre et mouvement réduit. Si un diff surprenait, il ne partait pas tant que quelqu’un ne l’expliquait pas en clair.
Un jour, un changement apparemment anodin a assombri légèrement la rampe neutre en mode sombre. Le diff a signalé que les bordures de tableau avaient presque disparu et que
le fond du code inline se confondait avec le paragraphe. Personne ne l’aurait remarqué en regardant une seule page, car la plupart des pages n’avaient pas de tableaux denses ou de code inline.
Parce que le diff l’a attrapé avant la sortie, la correction a été triviale : ajuster deux tokens sémantiques et ajouter un token de bordure plus fort.
Pas d’incident. Pas de hotfix. Pas de thread Slack d’urgence. Juste une PR normale et tout le monde est rentré chez soi à l’heure.
Listes de contrôle / plan pas-à-pas
Pas-à-pas : construire un thème de docs tokenisé depuis zéro
- Définir les surfaces et rôles de texte : bg, bg élevé, bg en retrait, fg, fg muted, border, border fort.
- Choisir une rampe neutre avec assez d’étapes pour supporter l’élévation et les bordures sans recourir aux hacks alpha.
- Définir des tokens sémantiques pour les liens, l’anneau de focus, la sélection et les surfaces de code.
- Définir des tokens de mouvement (durées + easing) et mettre en place des overrides pour le mouvement réduit.
- Implémenter la bascule de thème avec défaut système et override utilisateur via
data-theme. - Refactorer les composants pour consommer uniquement des tokens sémantiques ; autoriser les tokens de composant seulement pour de réelles contraintes.
- Ajouter des garde-fous : lint pour couleurs brutes, trouver les tokens non définis, interdire
transition: all. - Ajouter des snapshots de pages canoniques en clair/sombre/mouvement réduit.
- Publier et observer : surveillez les tickets de support pour contraste, focus et plaintes liées au mouvement ; ce sont des signaux, pas du bruit.
Checklist de release : avant de merger un changement de thème
- Aucune littérale de couleur brute introduite en dehors des fichiers de tokens (ou justifiée explicitement).
- Les tokens sémantiques mis à jour pour les modes clair et sombre.
- Focus visible sur tous les éléments interactifs dans les deux thèmes.
- Le mode mouvement réduit désactive le défilement fluide et les transitions majeures.
- Blocs de code lisibles : fond, sélection, commentaires et code inline testés.
- Tableaux : bordures et alternance de lignes restent visibles en mode sombre.
- Diffs de régression visuelle revus sur les pages canoniques.
- Le basculement de thème ne clignote pas au premier paint.
Checklist Ops : diagnostiquer une plainte de thème en production
- Reproduire avec les paramètres OS signalés par l’utilisateur (mode sombre, mouvement réduit, haut contraste si applicable).
- Vérifier si un attribut de thème forcé est appliqué tard par du JS (timing réseau, scripts bloqués, problèmes CSP).
- Inspecter les valeurs calculées des tokens sémantiques sur la page affectée.
- Chercher des overrides locaux et des règles
!importantprès du composant en échec. - Comparer avec les pages canoniques pour voir si le problème est systémique ou spécifique au contenu.
FAQ
1) Dois-je stocker les tokens en variables CSS ou les générer depuis un outil de design ?
Stockez le contrat runtime en variables CSS. Vous pouvez générer ce fichier depuis un outil si vous le souhaitez, mais conservez une sortie de tokens lisible par l’humain.
Quand la production casse, vous voulez déboguer dans le navigateur, pas dans une pipeline d’export.
2) À quel point le « mode sombre façon X » doit-il être proche du noir pur ?
Utilisez du presque-noir pour le fond de base, pas du noir pur. Le noir pur peut être agressif pour la lecture et rend l’élévation subtile plus difficile.
Le presque-noir vous donne de la marge pour surfaces et bordures sans contours néon.
3) Est-ce acceptable d’utiliser des overlays alpha pour des fonds subtils ?
Parfois. Les overlays alpha sont fragiles selon les fonds et peuvent s’effondrer en mode sombre. Préférez des tokens sémantiques explicites
pour les surfaces critiques (encarts, blocs de code). Utilisez l’alpha pour la décoration non critique, et testez sur les deux thèmes.
4) Ai-je besoin de tokens séparés pour les blocs de code ?
Oui, généralement. Les blocs de code ont des contraintes différentes : contenu dense, couleurs de syntaxe, styles de sélection et boutons de copie.
Traitez-les comme une surface avec fond, bordure et tokens de syntaxe explicites.
5) Quelle est l’implémentation de bascule de thème la plus simple qui n’éclaire pas l’écran au chargement ?
Par défaut, suivez la préférence système via la media query CSS. Appliquez data-theme seulement quand l’utilisateur choisit explicitement clair ou sombre.
Si vous devez l’appliquer au chargement, positionnez-le avant le premier paint avec un petit script inline dans le head.
6) Comment supporter le mouvement réduit sans réécrire tout le CSS ?
Tokenisez les durées de mouvement et référencez-les dans les transitions. Sous prefers-reduced-motion: reduce, overridez
les tokens de durée à quasi-zéro et désactivez le défilement fluide. Cela couvre la plupart des mouvements sans chasser chaque ligne de transition.
7) Pourquoi ne pas juste utiliser le thème d’un framework UI et en finir ?
Les thèmes de framework vont bien jusqu’à ce que votre site de docs ait des blocs de code, tableaux, encarts et composants spécifiques au contenu
qui n’étaient pas dans le chemin heureux du framework. Les tokens vous permettent d’adapter sans forker tout le CSS du framework ou lutter contre la spécificité pour toujours.
8) Combien de tokens est « trop » ?
Quand vous ne pouvez pas répondre « à quoi sert ce token » sans ouvrir Figma, vous en avez trop. Les tokens doivent encoder des décisions stables.
Si un token existe uniquement pour rendre un composant légèrement différent, c’est probablement du CSS composant, pas un token.
9) Les tokens aident-ils la fiabilité, ou est-ce juste de l’hygiène design ?
Ils aident la fiabilité parce qu’ils réduisent le rayon d’impact des changements. Un ajustement de token sémantique peut corriger le contraste sur tout le site
sans toucher le CSS des composants, et les tests de régression peuvent se concentrer sur la couche de tokens. C’est moins d’effets de bord étranges en production.
Conclusion : prochaines étapes qui ne vous feront pas perdre la semaine
Construisez le thème comme si vous gériez une production : définissez des contrats, réduisez les inconnues et gardez le rayon d’impact petit.
Les design tokens sont ce contrat. Les variables CSS sont le mécanisme runtime. Le mode sombre et le mouvement réduit ne sont pas des « fonctionnalités » — ce sont des attentes utilisateur que vous respectez ou non.
Prochaines étapes pratiques :
- Auditez votre CSS pour les couleurs brutes et
transition: all; déplacez les décisions dans des tokens sémantiques. - Implémentez un mode sombre par défaut système avec un override utilisateur explicite via
data-theme. - Ajoutez des tokens de mouvement et un override strict pour le mouvement réduit (y compris le défilement fluide).
- Créez 5–8 pages canoniques et exécutez des diffs visuels en clair/sombre/mouvement réduit avant de merger les changements de thème.
- Faites des bordures, tableaux, blocs de code, anneaux de focus et styles de sélection des citoyens de première classe des tokens. C’est là que les thèmes échouent réellement.
Si vous faites cela bien, personne ne complimentera votre thème de docs. Ils se contenteront de le lire. C’est ça la victoire.