Vous déployez une refonte de la doc le vendredi. Le lundi, votre rotation d’astreinte lit une case « DANGER » qui ressemble à une ASTUCE en mode sombre, et quelqu’un colle un jeton de production au mauvais endroit. Ce n’est pas « juste du CSS ». C’est un incident opérationnel avec une jolie police.
Les encadrés (NOTE/ASTUCE/ATTENTION/DANGER) sont de petits composants d’interface aux conséquences disproportionnées. Ils compressent le risque en une couleur, une bordure et quelques mots. Si votre theming est négligé, vous habituez les utilisateurs à ignorer ces boîtes — puis vous vous demandez pourquoi le runbook n’a pas été suivi.
Ce que font réellement les encadrés (et pourquoi les opérations devraient s’en soucier)
Dans la documentation, les admonitions sont l’équivalent des garde-corps UI. Ce n’est pas de la décoration ; ce sont des surfaces de contrôle. Une NOTE dit « ne soyez pas surpris ». Une ASTUCE dit « faites ceci pour aller plus vite ». Une ATTENTION dit « vous pouvez vous blesser ». Un DANGER dit « vous pouvez blesser tout le monde ».
Telle est l’intention. La réalité est plus crue : la plupart des encadrés sont implémentés comme une extension Markdown qui mappe vers une classe CSS, puis thématisés par ce qu’il se passe dans le design system cette semaine. En mode clair, ils paraissent corrects ; en mode sombre, ils deviennent une bouillie à faible contraste, ou pire, l’échelle de gravité s’inverse. Les utilisateurs cessent de faire confiance aux visuels et survolent le texte. Quand l’interface n’est pas fiable, les opérateurs fatigués font ce qu’ils savent faire : ils devinent.
Si vos états ATTENTION et DANGER ne sont pas clairement distinguables en mode sombre, vous avez un bug de fiabilité documentaire. Traitez-le comme tel.
Les variables CSS (propriétés personnalisées) sont le meilleur outil pour rendre les encadrés cohérents entre frameworks, pages et modes. Pas parce que c’est tendance, mais parce qu’elles vous donnent :
- Un seul endroit pour définir le sens (jetons), de nombreux endroits pour le consommer (composants).
- Un basculement à l’exécution (mode sombre, haut contraste) sans recompilation du CSS.
- Des valeurs de secours sûres quand un jeton est manquant ou remplacé par un paquet de thème « utile ».
Il y a une mentalité de fiabilité : votre UI documentaire doit se dégrader en toute sécurité. Si une variable manque, vous voulez une valeur par défaut terne, pas une bordure invisible et un texte gris sur gris.
« La doc est statique. » Certes. Tout comme les messages d’erreur de votre baie de stockage — jusqu’au moment où ils provoquent une panne.
Une idée paraphrasée à garder en tête : Idée paraphrasée : « Tout échoue ; concevez pour que l’échec soit sans conséquence grave. » — attribuée à la pensée fiabilité de John Allspaw
Blague n°1 : Le mode sombre, c’est comme le RAID — tout le monde le veut, et quelqu’un le configurera quand même mal.
Faits et historique à utiliser en réunion
Ce ne sont pas des anecdotes pour le plaisir. Ce sont des munitions pour les conversations « pourquoi consacrer du temps à la thématisation des encadrés ? ».
- Le balisage « admonition » prédate la plupart des outils de doc modernes. Sphinx a popularisé des directives comme
.. note::des années avant que les stacks Markdown d’aujourd’hui ne les normalisent. - Le Markdown de GitHub n’a pas standardisé les admonitions. Beaucoup d’écosystèmes ont implémenté leur propre syntaxe, d’où la galère de portabilité.
- Les propriétés personnalisées CSS sont disponibles largement depuis les navigateurs de l’ère 2017. Cela compte parce que « on ne peut pas compter sur les variables » est souvent une mémoire institutionnelle dépassée.
prefers-color-schemeest devenu pratique seulement après l’adoption du mode sombre au niveau OS. Avant cela, beaucoup de sites utilisaient un commutateur manuel et des hacks de cookie.- Les premiers thèmes sombres inversaient souvent les couleurs. L’inversion casse les couleurs sémantiques : les avertissements jaunes deviennent illisibles, les bleus deviennent néon et les gris deviennent bizarres. Le theming moderne ajuste la luminance, pas seulement la teinte.
- Les recommandations WCAG portent sur la lisibilité du texte, pas sur l’esthétique de la marque. « Ça a l’air correct sur mon MacBook » n’est pas une stratégie de contraste.
- Les couleurs d’encadré ont un bagage culturel. Le rouge signale le danger dans de nombreux endroits, mais pas partout. Voilà pourquoi l’iconographie et les étiquettes importent.
- Les design tokens sont apparus pour les systèmes UI multi-plateformes à grande échelle. Le but était la cohérence sur web/iOS/Android, pas seulement « du CSS plus propre ».
Jetons de design avec variables CSS : l’approche raisonnable
Arrêtez de penser aux encadrés comme « une boîte bleue » ou « une boîte jaune ». Pensez en jetons : accent, fond, bordure, et parfois couleur d’icône. Les jetons représentent le sens, pas l’implémentation.
Hiérarchie de jetons souhaitable
Une hiérarchie fiable prévient les « guerres d’overrides » aléatoires :
- Jetons de base globaux :
--bg,--fg,--border. - Jetons sémantiques :
--note-accent,--warn-bg, etc. - Jetons composant :
--callout-accent,--callout-borderdéfinis par la classe du composant.
Cela importe car les composants doivent consommer des jetons sémantiques, pas des valeurs hex brutes. Quand vous changez la couleur d’avertissement une fois, tout le site doit suivre. Le CSS ci-dessus fait exactement ça en mappant .callout.warn vers --warn-*.
Gardez les noms de jetons ennuyeux. Si vous nommez un jeton --sunset-glow-500, vous finirez par déployer un encadré DANGER « sunset ». Les utilisateurs seront ravis jusqu’à ce qu’ils suppriment le mauvais cluster.
Valeurs de secours : que se passe-t-il quand un jeton manque ?
Dans les systèmes de production, vous planifiez les dépendances manquantes. Pareil ici. Utilisez les valeurs de secours agressivement :
border: 1px solid var(--callout-border, var(--border));signifie « si la bordure de callout manque, utilisez la bordure globale ».- Ne jamais compter sur la
backgroundseule pour porter le sens. Les bordures et les titres survivent mieux aux collisions de thème. - Faites de l’étiquette textuelle (« ATTENTION », « DANGER ») un élément UI de première classe, pas un pseudo-élément qui se perd avec des remplacements de police.
Où les jetons doivent vivre
Placez les jetons aussi près que possible de la racine du document (:root). Si votre framework scope les styles, assurez-vous que les jetons restent globalement accessibles, ou sont intentionnellement scoppés par zone de docs. Mixer les modèles de scoping est la recette pour obtenir des encadrés qui s’affichent différemment dans la barre latérale et dans le contenu principal.
| Gravité | Jetons sémantiques | Utilisation par le composant | Objectif opérationnel |
|---|---|---|---|
| NOTE | --note-accent, --note-bg, --note-border |
.callout.note définit --callout-* |
Informer, ne pas distraire |
| ASTUCE | --tip-accent, --tip-bg, --tip-border |
Même modèle | Encourager les bonnes pratiques |
| ATTENTION | --warn-accent, --warn-bg, --warn-border |
Même modèle | Prévenir les erreurs |
| DANGER | --danger-accent, --danger-bg, --danger-border |
Même modèle | Arrêter les actions dangereuses |
Mode sombre sans tromperie visuelle
Le theming du mode sombre n’est pas « inverser et espérer ». Vos yeux s’adaptent différemment en faible luminosité, et vos couleurs se comportent différemment sur des fonds quasi noirs. Le principal mode d’échec : vous conservez les mêmes accents mais baissez le fond en opacité, et soudain le texte de l’étiquette est la seule chose lisible. Les utilisateurs interprètent toute la boîte comme « faible priorité », parce qu’elle visuellement recule.
Utilisez color-scheme et laissez la plateforme aider
Définissez color-scheme: light dark à la racine. Cela indique aux contrôles de formulaire et aux barres de défilement d’adopter le bon style. Ça réduit aussi la probabilité qu’un contrôle natif à l’intérieur d’un encadré ait l’air d’avoir été téléporté de 2009.
Choisissez une stratégie : teinter les fonds, puis corriger bordures et texte
En mode sombre, les fonds devraient généralement être teintés (faible alpha) et les bordures devraient être plus marquées que vous ne le pensez. Les bordures définissent la forme quand tout le reste est sombre. C’est pourquoi le CSS exemple utilise :
--*-bg: rgba(...,.10)pour des remplissages doux--*-border: rgba(...,.35)pour la forme et les indices de gravité
Si votre DANGER en mode sombre paraît plus calme que votre NOTE en mode clair, votre échelle de gravité est inversée. Les utilisateurs suivront l’échelle que vous affichez, pas celle que vous avez prévue.
Ne faites pas confiance à votre écran. Instrumentez votre thème.
Oui, vous devez faire de la QA visuelle. Mais vous devriez aussi traiter les variables CSS comme de la configuration et les vérifier en CI. Si votre paquet de thème se met à jour et change silencieusement --warn-accent, vous voulez un diff qui casse la build, pas une plainte client du type « les encadrés d’avertissement sont… relax ».
Blague n°2 : La seule chose plus sombre que le mode sombre, c’est l’âme de la personne qui a mergé « correction rapide de contraste » directement sur main.
Patrons d’implémentation pour les admonitions
Votre générateur de doc peut être Markdown, MDX, AsciiDoc, reStructuredText, ou quelque chose d’interne et maudit. Les patrons ci‑dessous survivent aux changements d’outil.
Patron A : HTML sémantique + classes
Rendez les admonitions comme un élément réel avec un titre. Évitez les pseudo‑éléments pour du texte critique ; ils sont fragiles pour les outils d’accessibilité et la traduction.
cr0x@server:~$ cat ./callout-example.html
<div class="callout warn" role="note" aria-label="Warning callout">
<div class="icon" aria-hidden="true"></div>
<div>
<div class="title">WARNING</div>
<p>Do not run this command against production.</p>
</div>
</div>
Décision : si votre pipeline ne peut pas émettre un HTML sémantique comme ceci, corrigez le pipeline. Le style est la partie facile ; la structure fiable est la partie dure.
Patron B : attributs data pour la gravité
Quand les docs sont générées à partir de contenu, les attributs data peuvent réduire la prolifération de classes :
<aside class="callout" data-kind="warn">- CSS :
.callout[data-kind="warn"] { ... }
Cela facilite aussi les requêtes dans les tests.
Patron C : un composant callout, plusieurs thèmes
Si vous avez plusieurs produits ou « espaces », ne forkez pas le CSS des callouts. Gardez un composant unique. Surchargez les jetons par espace.
Approche d’exemple :
:root[data-space="storage"] { --note-accent: ... }:root[data-space="compute"] { --note-accent: ... }
Opérationnellement, c’est comme ça que vous évitez la spirale de tickets « ATTENTION a l’air différent sur le produit A ».
Patron D : forced-color et support haut contraste
Le mode forced-colors de Windows ignorera votre belle palette. Tant mieux. Vous voulez que l’OS gagne. Ajoutez des règles minimales :
@media (forced-colors: active) { .callout { border: 1px solid CanvasText; } }- Assurez-vous que les titres restent visibles sans dépendre du fond.
Accessibilité : contraste, sémantique et « ne pas se fier à la couleur »
L’accessibilité n’est pas une taxe de conformité ; c’est comment vous maintenez le sens face à des conditions hostiles : écrans bon marché, soleil de plomb, mode migraine, ou une personne lisant à 03:00 sur un portable atténué en babysittant un incident.
Contraste : testez le texte, pas l’ambiance
Pour les encadrés, concentrez‑vous sur :
- Contraste du titre par rapport au fond de l’encadré.
- Contraste du corps par rapport au fond de l’encadré.
- Visibilité de la bordure par rapport au fond de la page.
Un piège courant : vous respectez le contraste sur le titre mais le ratez pour les liens à l’intérieur de l’encadré parce que la couleur des liens est globale. C’est pourquoi les jetons doivent prendre en compte le contraste des liens aussi (ou du moins éviter des fonds ultra‑clairs qui lavent les liens).
Sémantique : gardez l’étiquette et la gravité lisibles par machine
Utilisez une étiquette visible et pensez à aria-label. Un lecteur d’écran ne devrait pas avoir à déduire qu’une bordure est jaune. Les humains non plus.
Ne codez pas la gravité uniquement par la couleur
Utilisez au moins deux indices :
- Texte d’étiquette : NOTE/ASTUCE/ATTENTION/DANGER.
- Forme de l’icône (même simple).
- Épaisseur ou motif de bordure (subtil mais utile).
Si vos encadrés ne sont différenciés que par la teinte, vous construisez une UI qui échouera dès que quelqu’un imprimera la page ou utilisera un écran e‑ink en niveaux de gris.
Trois mini-histoires d’entreprise issues des tranchées du theming
Mini-histoire n°1 : un incident causé par une mauvaise hypothèse
Une entreprise de taille moyenne a migré sa documentation interne vers un nouveau générateur de site statique. Les responsables de contenu étaient ravis : builds plus rapides, pages plus belles, un commutateur mode sombre. La direction ingénierie a approuvé parce que « c’est la doc, pas la production ».
La migration incluait des admonitions. L’ancien système rendait WARNING et DANGER avec des icônes différentes et des bordures très distinctes. Le nouveau système utilisait la même icône pour les deux, et l’auteur du thème a supposé que le fond rouge pâle serait « évidemment dangereux ». En mode clair, c’était majoritairement vrai. En mode sombre, les fonds étaient des teintes à faible opacité et le fond de page quasi noir avalait la différence.
Un mois plus tard, quelqu’un suit un runbook pour faire tourner les credentials d’une intégration partagée. Il y avait un encadré DANGER : « Cette étape invalide les jetons pour tous les environnements ; coordonnez‑vous. » En mode sombre, cela ressemblait à un avertissement léger, la personne a supposé que l’impact était localisé, et elle a procédé seule.
Résultat : plusieurs services ont perdu l’authentification en quelques minutes. L’incident n’a pas été causé par une mauvaise conception d’authentification ; il a été causé par une mauvaise hypothèse sur la façon dont une UI communique le risque. La correction post‑incident n’a pas été « former les ingénieurs à mieux lire ». C’était : faire respecter la différenciation de gravité via des jetons, ajouter des contrôles de contraste automatisés, et exiger des icônes uniques pour WARNING vs DANGER.
Mini-histoire n°2 : une optimisation qui a mal tourné
Une autre organisation a décidé que leur bundle CSS était trop gros. Quelqu’un a proposé d’« optimiser » en supprimant les jetons sémantiques et en laissant la pipeline inliner les couleurs hex directement dans le CSS des composants. Moins de variables, moins d’octets, pages plus rapides. Le tableau de performance s’est amélioré un peu, ce qui explique comment ces idées se font promouvoir.
Puis un rafraîchissement de marque est arrivé. Le design system a mis à jour les couleurs d’accent. La plupart des composants ont repris la nouvelle palette parce qu’ils étaient basés sur des jetons. Mais les admonitions avaient maintenant des couleurs codées en dur dans un CSS compilé. La moitié des pages avaient les anciennes couleurs et l’autre moitié les nouvelles. En mode sombre, la nouvelle palette fonctionnait ; l’ancienne non. Les utilisateurs ont commencé à signaler que les boîtes WARNING étaient illisibles — seulement sur certaines sections de la doc.
L’équipe a passé des jours à courir après des « problèmes de cache » et des « propagations CDN ». La réalité était plus embarrassante : l’optimisation avait supprimé le point de vérité unique. La correction a été de restaurer les variables CSS, accepter un fichier CSS un peu plus gros, et mettre en place de vrais budgets : mesurer la taille du bundle, mais ne pas micro‑optimiser au détriment de la maintenabilité.
Ils ont aussi appris la leçon dure : un fichier CSS plus petit n’est pas « plus rapide » s’il déclenche plus de temps humain et plus d’erreurs en production. La latence ne se mesure pas qu’en millisecondes.
Mini-histoire n°3 : une pratique ennuyeuse mais correcte qui a sauvé la mise
Une grande équipe d’entreprise maintenait la doc d’une plateforme de stockage avec beaucoup de commandes « vous pouvez tout supprimer ». Leur doc était traitée comme partie du produit, ce qui signifiait que les changements passaient par la CI avec des tests. Pas spectaculaire. Très efficace.
Ils avaient une règle : les jetons pour les encadrés vivent dans un seul fichier, et chaque modification de ce fichier déclenche un run visuel plus une simple vérification de « présence des jetons ». Ils gardaient aussi une petite page appelée « échelle de gravité » qui rendait les quatre encadrés, avec liens et blocs de code, dans les deux modes.
Un jour, une mise à jour de dépendance a changé un jeton de fond de base. Ce n’était pas malveillant ; c’était une refactorisation. Les encadrés rendaient toujours, mais le contraste de la bordure ATTENTION a baissé et le fond DANGER est devenu trop subtil. Le job de régression visuelle l’a signalé avant la fusion.
Pas de drame, pas de rollback nocturne. La correction a été un petit ajustement de l’alpha de la bordure en mode sombre. Voilà ce que rapporte la « correction ennuyeuse » : vous attrapez les régressions sémantiques tôt, et votre doc n’apprend pas silencieusement aux gens la mauvaise façon.
Tâches pratiques : commandes, sorties et décisions
Les problèmes de theming de la doc se déboguent mieux comme tout autre problème de production : reproduire, mesurer, isoler, corriger, vérifier, puis prévenir les régressions. Ces tâches supposent un dépôt de docs statique typique avec un répertoire de build (par exemple build/ ou dist/), des assets CSS et un serveur de dev local.
Tâche 1 : Trouver où les admonitions sont rendues dans le HTML généré
cr0x@server:~$ rg -n "callout|admon|alert|data-kind" build/ -S | head
build/ops/runbook/index.html:214:<div class="callout warn" role="note" aria-label="Warning callout">
build/ops/security/index.html:88:<aside class="callout" data-kind="danger">
build/styles/main.css:1023:.callout.warn{--callout-accent:var(--warn-accent);}
Ce que cela signifie : Vous connaissez maintenant la forme DOM réelle et les sélecteurs utilisés en production.
Décision : Si la sortie varie par page (div vs aside), standardisez‑la. Un balisage incohérent garantit un style et des tests incohérents.
Tâche 2 : Localiser les définitions de jetons et confirmer qu’elles ne sont pas dupliquées
cr0x@server:~$ rg -n --hidden --glob '!**/node_modules/**' ":root|--note-accent|--warn-accent|--danger-accent" .
./src/styles/tokens.css:1::root{
./src/styles/tokens.css:22: --note-accent: #2563eb;
./src/styles/tokens.css:30: --warn-accent: #b45309;
./src/styles/tokens.css:38: --danger-accent: #dc2626;
./src/styles/theme-overrides.css:11::root{ --warn-accent: #a16207; }
Ce que cela signifie : Vous avez plusieurs définitions ; la dernière l’emporte à l’exécution.
Décision : Consolidez les jetons ou documentez la priorité des overrides. Si vous ne pouvez pas expliquer la priorité en une phrase, vous ne la maîtrisez pas.
Tâche 3 : Vérifier que le mode sombre est piloté par prefers-color-scheme et non par un toggle fragile
cr0x@server:~$ rg -n "prefers-color-scheme|data-theme=|class=.*dark" src/styles -S
src/styles/tokens.css:45:@media (prefers-color-scheme: dark){
src/styles/app.css:12:html[data-theme="dark"] .sidebar{ background: #0b1020; }
Ce que cela signifie : Vous mêlez mode sombre automatique et manuel.
Décision : Choisissez une source de vérité. Si vous supportez un toggle manuel, il doit écraser prefers-color-scheme de façon intentionnelle (et cohérente).
Tâche 4 : Lancer un serveur local et reproduire dans les deux modes
cr0x@server:~$ npm run dev
> docs@1.0.0 dev
> vite
VITE v5.4.0 ready in 430 ms
➜ Local: http://localhost:5173/
➜ Network: http://192.168.1.20:5173/
Ce que cela signifie : Vous disposez d’un environnement de reproduction fiable.
Décision : Si vous ne pouvez pas reproduire localement, ne « fixez » pas le CSS en production. Alignez d’abord les environnements de build (version de Node, lockfile, CI).
Tâche 5 : Confirmer les variables calculées finales dans le CSS buildé
cr0x@server:~$ rg -n --no-heading --fixed-strings "--warn-bg" build/assets/*.css | head -n 5
build/assets/main-9a8c1.css:1:...--warn-bg:#fffbeb;--warn-border:#fde68a;...
build/assets/main-9a8c1.css:1:...@media (prefers-color-scheme:dark){:root{--warn-bg:rgba(251,191,36,.1);--warn-border:rgba(251,191,36,.35)}}
Ce que cela signifie : Les jetons existent dans la sortie et ont des valeurs pour clair et sombre.
Décision : Si les overrides sombre manquent, votre build CSS peut tree‑shaker ou scoper les blocs media. Corrigez la config du bundler avant de retoucher les couleurs.
Tâche 6 : Vérifier si le sélecteur callout est override plus tard dans l’ordre du CSS
cr0x@server:~$ rg -n "\.callout\.warn|\[data-kind=\"warn\"\]" build/assets/*.css | head -n 20
build/assets/main-9a8c1.css:1023:.callout.warn{--callout-accent:var(--warn-accent);--callout-bg:var(--warn-bg);--callout-border:var(--warn-border)}
build/assets/vendor-a12ff.css:887:.callout{border:1px solid transparent;background:transparent}
Ce que cela signifie : Le CSS fournisseur peut réinitialiser votre composant callout après vos propres règles, selon l’ordre de chargement.
Décision : Corrigez l’ordre de chargement ou augmentez la spécificité avec précaution. Ne lancez pas une course à la spécificité ; vous perdrez et vous l’aurez mérité.
Tâche 7 : Contrôle rapide pour jetons manquants via une grep list
cr0x@server:~$ rg -o --no-filename "var\\(--[a-z0-9-]+\\)" -S src/styles | sort | uniq | head -n 20
var(--bg)
var(--border)
var(--callout-accent)
var(--callout-bg)
var(--callout-border)
var(--danger-accent)
var(--danger-bg)
var(--danger-border)
var(--fg)
var(--link)
var(--muted)
var(--note-accent)
var(--note-bg)
var(--note-border)
var(--tip-accent)
var(--tip-bg)
var(--tip-border)
var(--warn-accent)
var(--warn-bg)
var(--warn-border)
Ce que cela signifie : Vous avez un inventaire des variables référencées.
Décision : Comparez cela à ce que vous définissez dans :root. Les définitions manquantes doivent être traitées comme des échecs de build, pas comme « ça a l’air OK ».
Tâche 8 : Détecter les variables indéfinies en cherchant les fallbacks manquants
cr0x@server:~$ rg -n "var\\(--(note|tip|warn|danger)-[a-z-]+\\)" src/styles | head
src/styles/callouts.css:14:background: var(--warn-bg);
src/styles/callouts.css:15:border-color: var(--warn-border);
Ce que cela signifie : Ces références n’ont pas de fallback. Si les jetons manquent ou sont scoppés, vous obtenez des visuels cassés.
Décision : Pour les sémantiques critiques (ATTENTION/DANGER), ajoutez des fallbacks ou imposez la présence des jetons via des tests (préférez les tests).
Tâche 9 : Vérifier que le HTML inclut des étiquettes et pas seulement des icônes
cr0x@server:~$ rg -n "WARNING|DANGER|TIP|NOTE" build/ops -S | head
build/ops/runbook/index.html:216:<div class="title">WARNING</div>
build/ops/runbook/index.html:301:<div class="title">DANGER</div>
Ce que cela signifie : La gravité est présente en texte dans le DOM.
Décision : Si les étiquettes manquent, ajoutez‑les à la génération. Le style peut changer ; le texte est durable.
Tâche 10 : Créer une page « échelle de gravité » et s’assurer qu’elle build
cr0x@server:~$ ls -la src/pages/severity-ladder.md
-rw-r--r-- 1 cr0x cr0x 1482 Dec 28 10:22 src/pages/severity-ladder.md
Ce que cela signifie : Vous avez une page unique qui rend tous les états d’encadrés pour la QA et la régression visuelle.
Décision : Si vous n’avez pas cette page, créez‑la. C’est le canari pour les régressions de theming.
Tâche 11 : Confirmer que la CI génère la même sortie localement (sanité du lockfile)
cr0x@server:~$ node --version
v22.11.0
Ce que cela signifie : La version de Node est explicite.
Décision : Épinglez les versions de Node en CI. Les différences de sortie CSS dues aux versions d’outils existent et sont une façon stupide de perdre un mercredi.
Tâche 12 : Inspecter la composition du bundle pour voir où atterrit le CSS des callouts
cr0x@server:~$ ls -lh build/assets | head
total 1.6M
-rw-r--r-- 1 cr0x cr0x 92K Dec 28 10:35 main-9a8c1.css
-rw-r--r-- 1 cr0x cr0x 610K Dec 28 10:35 vendor-a12ff.css
-rw-r--r-- 1 cr0x cr0x 120K Dec 28 10:35 main-9a8c1.js
-rw-r--r-- 1 cr0x cr0x 740K Dec 28 10:35 vendor-a12ff.js
Ce que cela signifie : Le CSS est split ; l’ordre de chargement compte.
Décision : Assurez‑vous que les définitions de jetons chargent avant les composants, et les composants avant les overrides. Si votre bundler réordonne, vous avez besoin d’imports explicites.
Tâche 13 : Détecter la duplication accidentelle du CSS des callouts à travers les bundles
cr0x@server:~$ for f in build/assets/*.css; do echo "== $f"; rg -n "\.callout(\.|\[)" "$f" | head -n 3; done
== build/assets/main-9a8c1.css
1023:.callout.warn{--callout-accent:var(--warn-accent);--callout-bg:var(--warn-bg);--callout-border:var(--warn-border)}
1030:.callout.danger{--callout-accent:var(--danger-accent);--callout-bg:var(--danger-bg);--callout-border:var(--danger-border)}
== build/assets/vendor-a12ff.css
887:.callout{border:1px solid transparent;background:transparent}
Ce que cela signifie : Vous avez le style de base des callouts dans vendor, et le mapping de gravité dans main.
Décision : Ça peut aller, mais documentez‑le. Si le vendor change, le comportement de votre composant change. Envisagez de déplacer les styles de base du callout dans votre propre bundle pour la stabilité.
Tâche 14 : Vérifier que les couleurs des liens dans les encadrés restent lisibles dans les deux modes
cr0x@server:~$ rg -n "a\\{|--link" src/styles -S
src/styles/tokens.css:14: --link: #0b5fff;
src/styles/tokens.css:15: --link-visited: #6a2cff;
src/styles/app.css:66:a{ color: var(--link); }
Ce que cela signifie : Les liens sont basés sur des jetons, vous pouvez donc les ajuster globalement si les fonds d’encadré changent.
Décision : Si les liens sont codés en dur, déplacez‑les vers des jetons. Les encadrés sont l’endroit où les gens cliquent « En savoir plus » juste avant de faire quelque chose de risqué.
Fiche de diagnostic rapide
Quand quelqu’un signale « les encadrés sont mauvais en mode sombre », vous voulez trouver le goulot rapidement. Pas élégamment. Rapidement.
Premier point : confirmer que le symptôme est sémantique, pas esthétique
- Les ATTENTION et DANGER sont‑ils distinguables d’un coup d’œil ?
- L’étiquette est‑elle visible ?
- Le texte du corps est‑il lisible sans zoom ?
Pourquoi : Si la sémantique est intacte, vous pouvez planifier une correction d’ergonomie. Si la sémantique est cassée, traitez‑la comme un défaut hautement prioritaire.
Second point : identifier la source de vérité pour l’état du thème
- Le mode sombre est‑il piloté par
prefers-color-scheme? - Existe‑t‑il un toggle manuel (
data-theme, une classe surhtml) ? - Les deux sont‑ils actifs et se battent ?
Pourquoi : « Le mode sombre est faux » signifie souvent « nous avons deux modes sombres ».
Troisième point : vérifier la présence des jetons et l’ordre des overrides
- Les
--warn-*et--danger-*sont‑ils définis dans:root? - Les overrides mode sombre existent‑ils dans le CSS final ?
- Un CSS fournisseur réinitialise‑t‑il le composant après vos règles ?
Pourquoi : Si les jetons sont corrects mais que le composant est overridé plus tard, votre correction est d’ordre, pas de sélection de couleur.
Quatrième point : vérifier les bugs de scoping
- Les jetons sont‑ils définis sous un conteneur qui n’inclut pas le contenu docs ?
- Les admonitions sont‑elles rendues dans un iframe ou un shadow root ?
Pourquoi : Les variables CSS s’héritent. Si vos encadrés ne sont pas dans la portée, ils n’obtiendront pas les valeurs.
Cinquième point : lancer une régression visuelle ciblée sur la page échelle de gravité
- Comparer captures clair vs sombre
- Différencier le fichier de jetons CSS
Pourquoi : Les régressions visuelles sont faciles à débattre. Les diffs, moins.
Erreurs courantes : symptôme → cause racine → correctif
1) Symptôme : DANGER ressemble à NOTE en mode sombre
Cause racine : Le mode sombre utilise des teintes à faible opacité pour tous les encadrés, mais les accents ont une luminance trop similaire. Ou l’alpha de la bordure est trop faible pour se lire contre le fond de page.
Correctif : Augmentez le contraste des bordures pour les sévérités supérieures. Faites la bordure DANGER plus marquée que ATTENTION. Envisagez une bordure gauche subtile ou une bordure plus épaisse pour DANGER uniquement.
2) Symptôme : le fond de l’encadré disparaît sur certaines pages
Cause racine : Les jetons sont scoppés sur un conteneur qui n’est pas présent sur ces pages (par exemple, jetons définis sur .docs-layout alors que les pages de destination utilisent .marketing-layout).
Correctif : Déplacez les jetons sémantiques vers :root ou assurez‑vous que les deux layouts héritent d’un wrapper racine partagé.
3) Symptôme : les bordures sont transparentes même si le CSS les définit
Cause racine : Une autre feuille de style plus tard dans la cascade définit .callout { border-color: transparent; } ou réinitialise les bordures.
Correctif : Corrigez l’ordre d’import. Si vous ne pouvez pas, rendez la règle du composant plus spécifique de façon contrôlée (par exemple main .callout), pas avec !important partout.
4) Symptôme : seule l’icône est colorée ; tout le reste est gris
Cause racine : Le composant n’applique que --callout-accent et pas les jetons de fond/bordure, ou le mapping de la classe de gravité vers les jetons est manquant.
Correctif : Mappez chaque gravité vers les trois jetons : accent, fond, bordure. Le theming partiel produit une UI ambiguë.
5) Symptôme : les liens dans les encadrés sont illisibles en mode sombre
Cause racine : Les jetons globaux de liens ont été pensés pour le fond de page, pas pour des fonds d’encadré teintés ; le contraste chute à l’intérieur des encadrés.
Correctif : Ajustez les jetons globaux ou définissez un jeton de lien spécifique aux encadrés, par exemple .callout a{ color: var(--callout-link, var(--link)); }, avec overrides par gravité si nécessaire.
6) Symptôme : l’impression/PDF perd les distinctions de gravité
Cause racine : Dépendance aux teintes de fond et à une signification portée uniquement par la couleur ; les styles d’impression désactivent souvent les fonds.
Correctif : Ajoutez du CSS pour l’impression : conservez les bordures et les étiquettes, et envisagez des bordures à motif (plein vs double) pour les gravités élevées.
7) Symptôme : les admonitions paraissent différentes entre pages MDX et markdown
Cause racine : Des renderers différents émettent du HTML différent, donc vos sélecteurs matchent l’un mais pas l’autre.
Correctif : Normalisez la sortie au niveau du renderer, ou écrivez des sélecteurs couvrant volontairement les deux structures (et testez‑les).
8) Symptôme : le toggle sombre fonctionne, mais les encadrés ne changent pas
Cause racine : Les jetons ne sont définis que dans @media (prefers-color-scheme: dark), mais votre toggle utilise html[data-theme="dark"].
Correctif : Mettez les overrides sous les deux mécanismes, ou mieux : unifiez sur une méthode. Si vous devez supporter les deux, implémentez : « le toggle l’emporte sur la media query ».
Listes de contrôle / plan étape par étape
Étape par étape : construire des encadrés qui survivent aux changements de thème
- Standardiser le balisage : une forme DOM unique pour toutes les admonitions (y compris l’étiquette titre) pour tous les types de contenu.
- Définir les jetons de base dans
:root: fond, premier plan, bordures, couleurs de lien. - Définir les jetons sémantiques :
--note-*,--tip-*,--warn-*,--danger-*. - Mapper la gravité aux jetons du composant : dans le composant callout, définir
--callout-accent,--callout-bg,--callout-border. - Implémenter des fallbacks au point de consommation du composant (bordures, fond) pour que les jetons manquants se dégradent en sécurité.
- Supporter le mode sombre avec des overrides explicites sous
@media (prefers-color-scheme: dark)et/ou votre mécanisme de toggle choisi. - Ajouter une page échelle de gravité qui rend toutes les gravités avec liens et blocs de code.
- Ajouter un check CI de « présence des jetons » : parser le CSS ou grep la sortie buildée pour les jetons requis.
- Ajouter des tests de régression visuelle pour la page échelle de gravité en modes clair et sombre.
- Définir des règles de revue : tout changement de jetons nécessite un diff d’écran et une vérification de contraste.
Checklist opérationnelle : avant de merger un changement de thème
- ATTENTION et DANGER sont visuellement distincts dans les deux modes sans lire le corps.
- Les étiquettes sont présentes et lisibles.
- Les liens à l’intérieur des encadrés restent lisibles et clairement identifiables comme liens.
- Les styles d’impression préservent bordures et étiquettes.
- Les mises à jour du CSS fournisseur ne peuvent pas override les jetons silencieusement (ordre d’import vérifié).
- L’état du mode sombre a une source de vérité (ou une règle de priorité documentée).
- La page échelle de gravité passe les diffs de régression visuelle.
Si votre « définition de fini » pour le theming de la doc est « ça a l’air correct sur mon laptop », vous n’avez pas de définition de fini. Vous avez des vibes.
FAQ
1) Les encadrés doivent-ils utiliser <aside> ou <div> ?
Utilisez <aside> quand le contenu est tangentiel au flux principal (ce que sont souvent les encadrés). Utilisez <div> si votre générateur ne peut pas émettre de façon fiable <aside>. La cohérence compte plus que la perfection sémantique.
2) Thématiser les encadrés avec des couleurs hex ou HSL ?
Utilisez ce que votre équipe peut maintenir. HSL peut faciliter les ajustements de luminance pour le mode sombre, mais seulement si votre équipe l’utilise réellement. Les jetons sont la partie importante, pas le format couleur.
3) prefers-color-scheme suffit-il, ou ai‑je besoin d’un toggle manuel ?
Pour la doc publique, prefers-color-scheme est un bon défaut. Un toggle manuel est utile quand les gens travaillent en environnements mixtes (présentations, partage d’écran) ou quand les réglages OS sont verrouillés. Si vous ajoutez un toggle, faites‑en un override prévisible de la media query.
4) Comment empêcher une mise à jour de dépendance de casser les couleurs des encadrés ?
Deux leviers : (1) gardez vos jetons dans votre repo, pas dans un thème fournisseur que vous ne contrôlez pas ; (2) ajoutez des régressions visuelles et des vérifications de présence de jetons en CI. Traitez les changements de jetons comme des changements d’API.
5) Pourquoi ne pas utiliser !important pour stopper les overrides ?
Parce que vous gagnerez la bataille et perdrez la guerre. !important ne scale pas et casse l’extensibilité du theming. Corrigez l’ordre et le scoping d’abord. Si vous devez l’utiliser, appliquez‑le aux jetons à la racine, pas à chaque propriété de chaque composant.
6) Les encadrés ont‑ils besoin d’icônes différentes par gravité ?
Oui, si vous voulez que les utilisateurs différencient rapidement la gravité. Au minimum, ATTENTION et DANGER ne doivent pas partager la même icône. Associez icône + étiquette + couleur pour la redondance.
7) Quelle couverture minimale de tests pour les encadrés ?
Au moins une page qui rend toutes les gravités, en modes clair et sombre, sous régression visuelle. Ajoutez un contrôle textuel rapide vérifiant la présence des jetons dans le CSS buildé. C’est peu coûteux et ça attrape la classe de pannes « fichier de jetons non importé ».
8) Comment gérer les encadrés dans des conteneurs imbriqués (onglets, accordéons, barres latérales) ?
Assurez‑vous que les variables sont définies dans :root ou héritées dans ces conteneurs. Évitez de scoper les jetons à un wrapper layout que certaines pages n’utilisent pas. Si un conteneur change volontairement le fond, envisagez des ajustements spécifiques au conteneur via des jetons additionnels (mais gardez le mapping de gravité cohérent).
9) Les fonds teintés sont‑ils requis pour les encadrés ?
Non. Des bordures plus une étiquette forte peuvent suffire, et souvent impriment mieux. Les fonds teintés sont une aide à la lisibilité, pas le signal principal de gravité.
10) Comment garder les encadrés cohérents entre plusieurs sites de doc ?
Fournissez un composant callout CSS unique et un fichier de jetons. Autorisez chaque site à override les jetons, pas les règles du composant. C’est comme ça que vous obtenez de la flexibilité de marque sans dérive sémantique.
Conclusion : prochaines étapes durables
Si vous voulez des encadrés qui ne vous trahissent pas, traitez‑les comme une interface opérationnelle, pas une décoration. Vous encodez du risque. Rendez cet encodage stable.
- Normaliser le balisage des admonitions pour que vos sélecteurs ne fassent pas d’hypothèses.
- Déplacer les couleurs de gravité dans des variables CSS (jetons sémantiques), et les mapper dans un composant callout unique.
- Implémenter le mode sombre comme des overrides explicites de jetons, pas comme des effets secondaires accidentels.
- Ajouter une page échelle de gravité et l’intégrer à la CI avec un diff visuel.
- Adopter une règle ennuyeuse : les changements de jetons exigent une revue comme les changements de code, car c’en sont.
Quand votre UI documentaire communique correctement le risque, les utilisateurs font moins de suppositions. Moins de suppositions signifie moins d’incidents. Le calcul est rude mais constant.