12k
All articles

Auditer une feuille de styles avec Project Wallace

Un audit CSS avec Project Wallace transforme couleurs uniques, tailles de police, spécificité, doublons et taille de fichier en correctifs concrets.

OpenReplay Team
OpenReplay Team
Auditer une feuille de styles avec Project Wallace

Réaliser un audit CSS avec Project Wallace consiste à coller une feuille de styles dans l’analyseur en ligne et à lire cinq chiffres : le nombre de couleurs uniques, le nombre de tailles de police uniques, la spécificité maximale des sélecteurs (accompagnée du nombre d’id et de !important), l’écart entre le total des déclarations et les déclarations uniques, et le poids du fichier non compressé comparé à son poids gzip. Chaque chiffre pointe vers une modification différente.

Si votre feuille de styles a trois ans, vous soupçonnez probablement déjà qu’elle a dérivé. Ce qui vous manque, c’est un chiffre à inscrire dans un ticket. « Le CSS semble désordonné » ne sera jamais priorisé ; « nous livrons six gris là où le design en définit deux » le sera.

Cet article passe une petite feuille de styles d’exemple dans l’analyseur, lit le résultat métrique par métrique, et associe chaque constat à la modification concrète qu’il doit déclencher. Il traite du diagnostic. L’article suivant, How to Organize CSS in Modern Web Projects, traite du traitement.

Points clés

  • Les navigateurs écartent le CSS qu’ils ne peuvent pas analyser ou qu’ils ne reconnaissent pas et continuent le rendu : une feuille de styles accumule donc des erreurs sans jamais faire échouer un build.
  • Lorsque vous collez ou téléversez du CSS, Project Wallace exécute l’analyse dans un WebWorker sur votre propre appareil : la feuille de styles ne quitte jamais le navigateur.
  • L’écart entre les couleurs uniques livrées et la palette définie par le design est la forme mesurable de la dérive de design, et le correctif consiste à consolider les valeurs en tokens, pas à supprimer des règles.
  • Un pic de spécificité au milieu d’une feuille de styles coûte plus cher qu’un maximum élevé à la fin, car chaque surcharge ultérieure doit grimper au même niveau.
  • Les règles vides constituent le seul correctif d’audit qui ne nécessite jamais de vérification de régression visuelle ; les déclarations en doublon exigent, elles, du discernement avant suppression.

Pourquoi un audit CSS détecte-t-il ce que le build ne voit pas ?

Un navigateur qui rencontre une déclaration CSS qu’il ne peut pas analyser ou qu’il ne reconnaît pas écarte cette déclaration et poursuit le rendu de la page : c’est pourquoi une feuille de styles peut accumuler des erreurs pendant des années sans qu’un seul build échoue. Cette récupération relève d’un comportement spécifié. Selon les règles de gestion des erreurs du CSS Syntax Module Level 3, la déclaration incomplète est abandonnée, l’analyseur avance jusqu’au point-virgule suivant, et l’analyse normale reprend à partir de là.

La conséquence est que les dégâts en CSS ne ressemblent jamais à un échec. Ils ressemblent à une dérive : un quatrième gris à deux points du troisième, un titre en 17px entre les paliers 16px et 18px, un sélecteur d’id ajouté sous la pression d’une échéance, puis un !important ajouté pour le battre. Rien de tout cela ne casse quoi que ce soit. Tout cela rend la modification suivante plus difficile.

Comment lancer l’analyseur Project Wallace ?

L’analyseur CSS de Project Wallace accepte trois types d’entrée : l’URL d’un site web, un fichier téléversé, ou du CSS collé directement. Lorsque vous collez ou téléversez du CSS, le travail se fait localement : un WebWorker sur votre propre appareil réalise l’analyse, et rien de ce que vous collez n’est envoyé où que ce soit. Cette conception date de la réécriture de l’analyseur en 2021. Le mode URL, par nature, récupère le site cible sur le réseau avant l’analyse.

La page de saisie propose une option « Prettify CSS? », accompagnée d’une note avertissant que cette option modifie légèrement les chiffres. Choisissez un réglage et conservez-le pour toutes les analyses que vous souhaitez comparer.

Voici la feuille d’exemple. Trois contributeurs, deux ans, un header et un composant card :

/* header.css — three contributors, two years */
#site-header {
  background: #f5f5f5;
  color: #333333;
  font-size: 16px;
}

#site-header .nav-link {
  color: #343434;
  font-size: 15px;
  padding: 8px 12px;
}

.nav-link:hover {
  color: #222222 !important;
}

.card {
  background: #f4f4f4;
  color: #333333;
  font-size: 1rem;
  padding: 16px;
}

.card .card-title {
  font-size: 18px;
  color: #333333;
}

.card--featured .card-title {
  font-size: 17px;
  font-weight: 700 !important;
}

.legacy-banner {
}

.footer {
  background: #f5f5f5;
  color: #444444;
  font-size: 14px;
}

Ce qui revient est une page de résultats regroupée selon les mêmes catégories que la documentation des métriques : Stylesheet, Atrules, Rules, Selectors, Declarations, Properties et Values. Il y a bien plus d’une centaine de métriques. Les cinq ci-dessous sont celles qui se transforment en commit.

Que vous apprennent les couleurs et tailles de police uniques ?

L’écart entre le nombre total de couleurs et le nombre de couleurs uniques indique la fréquence de réutilisation de chaque couleur, et l’écart entre les couleurs uniques et la palette définie par votre design system indique à quel point le code a dérivé du design. L’analyseur compte les deux et vous fournit la liste complète des couleurs uniques trouvées ; les tailles de police bénéficient du même traitement.

Lue à la main, la feuille d’exemple contient six chaînes hexadécimales distinctes : #f5f5f5 et #f4f4f4 pour les surfaces, puis #333333, #343434, #222222, #444444 pour le texte. Un design system pour ce composant en prévoyait presque certainement une surface et deux couleurs de texte. L’échelle typographique est pire : 16px, 15px, 1rem, 18px, 17px, 14px font six valeurs telles qu’écrites, et 16px et 1rem se résolvent de toute façon généralement à la même taille en pixels.

Le correctif est la consolidation, pas la suppression. Consolider des gris quasi identiques ne signifie pas supprimer des règles ; cela signifie remplacer chaque littéral par le token le plus proche et laisser la règle continuer à jouer son rôle :

:root {
  --color-surface: #f5f5f5;
  --color-text: #333333;
  --color-text-muted: #444444;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
}

.card {
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--font-size-base);
  padding: 16px;
}

Trois tokens de couleur remplacent six littéraux ; trois tokens de taille en remplacent six. L’outil distinct Design Tokens de Project Wallace extrait les couleurs et tailles de police candidates du CSS existant, ce qui constitue un point de départ plus rapide que de lire la liste à la main sur une vraie feuille de styles.

Spécificité : les pics comptent plus que le maximum

Un sélecteur à forte spécificité situé vers la fin d’une feuille de styles est un problème local, mais un sélecteur au milieu oblige chaque règle ultérieure devant le surcharger à grimper au même niveau, et cette escalade est précisément la façon dont les sélecteurs d’id et les !important se multiplient. Le graphe de spécificité de Harry Roberts défend le même argument visuellement : la tendance devrait monter doucement vers la fin, et tout pic est un coût payé par tout ce qui suit.

L’analyseur rapporte la spécificité sous forme d’une valeur en trois parties (id, classe, type) via Maximum selector specificity, Total selectors having maximum specificity et Top specificity selectors, aux côtés de Total id selectors, Total !important declarations et Ratio of !important declarations.

La feuille d’exemple illustre le mécanisme en miniature. #site-header .nav-link se situe à (1,1,0). Le .nav-link:hover ultérieur, à (0,2,0), ne peut pas le battre : un contributeur a donc dégainé un !important. Un sélecteur d’id a produit un !important, et le second, sur .card--featured .card-title, bat une règle qui n’a jamais défini font-weight du tout.

Le nombre de sélecteurs d’id et le nombre de !important sont les deux chiffres de spécificité qu’une équipe peut réduire un commit à la fois, en remesurant après chaque modification. Dans l’exemple, passer le markup de id="site-header" à class="site-header" aplatit les deux règles du header à (0,1,0) et (0,2,0), et les deux !important deviennent inutiles.

Déclarations en doublon et règles vides

Une règle vide consomme des octets et une correspondance de sélecteur mais ne change rien à ce que l’utilisateur voit : la supprimer est donc le seul correctif d’audit qui ne nécessite jamais de vérification de régression visuelle. Les déclarations en doublon, c’est autre chose : la même intention écrite deux fois est un code smell, mais supprimer la mauvaise copie modifie la cascade.

L’analyseur compte directement les Total empty rules ; .legacy-banner {} est l’unique instance de l’exemple, et elle disparaît. Il n’existe pas de métrique autonome pour les déclarations en doublon. Comparez Total declarations à Total unique declarations et considérez l’écart comme le nombre de doublons, en gardant à l’esprit que la documentation laisse encore ouverte la question de savoir si les espaces ou le formatage rendent deux déclarations distinctes.

color: #333333 apparaît dans trois règles de l’exemple. La bonne démarche n’est pas de supprimer deux copies, mais de faire passer les trois par var(--color-text), ce qui rend la répétition visible comme une décision partagée plutôt que comme une coïncidence.

Pourquoi le poids gzip masque-t-il une feuille de styles boursouflée ?

Gzip compresse efficacement la répétition : une feuille de styles remplie de déclarations en doublon peut donc afficher une taille compressée flatteuse alors que sa taille non compressée, les octets réellement analysés par le navigateur, continue de croître. L’analyseur rapporte ensemble Uncompressed filesize, Gzip filesize et Gzip filesize compression ratio.

Un taux de compression qui augmente est le signe révélateur : il signifie que la feuille de styles devient plus répétitive, pas plus petite. Ce qui fait bouger la taille non compressée, c’est le nombre de règles et de déclarations, et c’est pourquoi le travail de consolidation évoqué plus haut la réduit par effet de bord. Le poids du fichier est un diagnostic à lire après les autres correctifs, pas une cible à optimiser pour elle-même.

Suivre une feuille de styles au fil des releases

Pour suivre une feuille de styles au fil des releases, conservez le CSS brut de chaque release à côté de ses résultats d’analyse et relancez chaque analyse avec le même réglage Prettify. Le CSS Diff viewer formate deux feuilles de styles collées et les compare ligne par ligne dans le navigateur, ce qui montre où le nombre de couleurs uniques ou de sélecteurs d’id a bougé.

Conclusion

Un audit de feuille de styles justifie le temps investi quand chaque chiffre correspond à une modification : les couleurs et tailles de police uniques vers des tokens, les sélecteurs d’id et les !important vers une spécificité plus plate, les règles vides vers la suppression, les doublons vers des déclarations partagées, et le poids du fichier vers une vérification que le reste a fonctionné. Collez votre plus grosse feuille de styles de production dans l’analyseur, notez ces cinq chiffres, et ouvrez une pull request par chiffre.

FAQ

Puis-je exécuter l'analyseur Project Wallace en ligne de commande ou en CI ?

Oui. Le package npm wallace-cli exécute le même analyseur dans un terminal : installez-le avec npm install wallace-cli, puis lancez wallace path/to/styles.css ou transmettez le CSS via stdin, et ajoutez le flag --json pour obtenir une sortie exploitable par machine dans vos scripts CI. La version 4.x de la CLI requiert Node 20.12 ou ultérieur. Pour un usage programmatique, importez la fonction analyze depuis @projectwallace/css-analyzer, un package uniquement ESM qui fonctionne à la fois dans Node et dans les navigateurs.

Dois-je analyser mes fichiers source Sass ou Tailwind, ou le CSS compilé ?

Analysez le CSS compilé que reçoivent vos utilisateurs, pas les sources Sass, Less ou Tailwind. Les variables, mixins et @extend sont développés au moment du build : les fichiers source faussent donc le comptage des couleurs uniques, le nombre de sélecteurs et le poids du fichier. Le plugin Stylelint de Project Wallace dit la même chose quant à la cible à viser : pointez-le vers le bundle que vous livrez, car les comptages de valeurs uniques et les ratios qui en découlent décrivent le fichier livré plutôt que la source. Le mode URL récupère déjà les feuilles de styles compilées servies par un site.

Quelle est la différence entre le CSS Analyzer de Project Wallace et son outil CSS Code Quality ?

Le CSS Analyzer rapporte des métriques brutes ; l'outil CSS Code Quality reprend cette sortie, y applique ses propres vérifications et ramène le résultat à trois scores sur 100 : Performance, Maintainability et Complexity. Utilisez l'analyseur quand vous devez remonter d'un chiffre à une règle précise, et Code Quality quand vous voulez un résumé argumenté à partager avec une équipe. Les deux acceptent une URL, des fichiers téléversés ou du CSS collé.

Comment éviter que les couleurs uniques ou la spécificité ne régressent après un audit ?

Ajoutez @projectwallace/stylelint-plugin à votre configuration Stylelint. Il embarque plus de 60 règles bâties sur le même moteur d'analyse, dont projectwallace/max-unique-colors, et son preset holistic évalue le fichier dans son ensemble (totaux, moyennes, ratios, unicité) au lieu de vérifier un nœud à la fois. Un preset recommended vous permet de démarrer avec une seule ligne extends. Exécutez-le sur le bundle CSS compilé en CI, afin qu'une pull request ajoutant un septième gris échoue avant le merge.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.