Embellir ou minifier : à quoi sert chacun, et ce que ça change au poids
Publié le 10/08/2026 · 15 min de lecture · Outils pour développeurs
Daniel Okonkwo — Développeur front-end et rédacteur Tech chez Allin
Performance web · Formats de fichiers
Vérifié à partir de 4 sources
Embellir sert à lire ; minifier sert à livrer. L'argument du poids est bien plus faible que le nombre d'octets bruts ne le laisse croire, parce que tout ce que tu livres passe par gzip et que gzip gère déjà la répétition — or l'indentation est le texte le plus répétitif qui soit. Quatre feuilles de style sont passées dans ce minifieur, les deux tailles relevées. Un composant de carte écrit à la main est passé de 1 612 à 1 118 octets, soit 30,6 % en moins ; gzippé, de 659 à 555, un gain de 104 octets. Séparer les deux passes est la vraie leçon. Sur les mêmes quatre fichiers, retirer les espaces seules a fait gagner 48, 103, 104 et 147 octets compressés — une centaine environ, quelle que soit la taille, de 1,6 ko à 22 ko. Retirer les commentaires seuls a fait gagner 57, 1 358, 2 420 et 1 042 octets. Sur un fichier très commenté, les commentaires représentent 96 % du gain réel ; les espaces, une erreur d'arrondi. Minifie donc pour les commentaires et le code mort, pas pour les retours à la ligne, et jamais au prix de la justesse. Ce minifieur-ci tient en cinq expressions régulières et casse cinq choses : il supprime l'espace que le CSS exige de part et d'autre du + dans calc(), si bien que calc(100% + 16px) devient une déclaration invalide que le navigateur jette ; il modifie l'intérieur des chaînes, transformant content: "a; b" en "a;b" ; il efface une chaîne qui ressemble à un commentaire ; il avale une séquence de commentaire dans un data-URI ; et il réécrit a[title="hello, world"]. Le même site propose css-compressor, un analyseur qui n'en casse aucune et pèse 2 octets de plus sur un fichier de 22 746 octets.
Quatre vraies feuilles de style passées au minifieur, mesurées brutes puis après gzip. Retirer toutes les espaces a fait gagner 48, 103, 104 et 147 octets compressés ; retirer les commentaires, 57, 1 358, 2 420 et 1 042. Et les cinq entrées que ce minifieur casse.
La mesure que la plupart des articles sautent : après gzip
Un minifieur annonce le nombre d'octets bruts parce que c'est le seul qu'il sait calculer. Ce n'est pas celui qui voyage. Toute feuille de style servie en HTTP arrive compressée, et les deux opérations se recouvrent : gzip encode une suite d'octets répétés en une courte référence arrière, et quatre espaces d'indentation répétés trois cents fois sont la chose la moins chère qu'il rencontrera jamais. Retirer cette indentation avant de compresser supprime un travail que gzip faisait gratuitement.
Les deux passes ont donc été séparées et mesurées chacune de son côté. Retirer seulement les commentaires, puis seulement les espaces, puis les deux, sur quatre fichiers : un composant de carte écrit à la main de 1 612 octets, et trois feuilles de style prises telles quelles dans le dépôt de ce site. Compressée en gzip niveau 9, la passe d'espaces a fait gagner 48, 103, 104 et 147 octets. Pas des pourcentages : des octets, et à peu près la même centaine que le fichier fasse 1,6 ko ou 22 ko, parce qu'il n'y a qu'un nombre limité d'indentations distinctes dans une feuille de style, si longue soit-elle. La passe de commentaires, sur les mêmes quatre fichiers, a fait gagner 57, 1 358, 2 420 et 1 042 octets compressés.
Un fichier suffit à faire la démonstration. Le globals.css de ce site pèse 7 148 octets, dont une bonne part est de la prose expliquant le choix de chaque couleur. Retirer les espaces l'a fait passer de 3 140 octets gzippés à 3 036 : 104 octets, 3,3 %. Retirer les commentaires l'a fait tomber à 720, soit 2 420 octets gagnés, 77 %. Quatre-vingt-seize pour cent du gain réel venaient des commentaires, et rien des retours à la ligne. Voilà tout l'argument dans un seul fichier : minifie pour retirer ce que le navigateur ne peut pas utiliser, pas pour retirer ce dont le compresseur s'occupe déjà.
Embellir ne coûte presque rien une fois compressé
La symétrie vaut dans l'autre sens, et c'est la partie utile. L'exemple fourni par l'embellisseur HTML est une page minifiée de 485 octets. Embellie avec une indentation de deux espaces, elle passe à 627 octets : 142 de plus, une hausse de 29,3 %, le chiffre qui inquiète. Gzippée, elle passe de 343 à 369 octets : 26 octets, 7,6 %. Vingt-six octets, ce n'est rien. Si tu livres une page lisible pour une raison — un exemple de documentation, un modèle d'e-mail que quelqu'un doit modifier, une page dont tu veux que le code source soit consultable — le coût compressé de la lisibilité est inférieur à une requête de favicon.
L'embellisseur HTML mérite aussi qu'on comprenne ce qu'il refuse de faire. Il recopie le contenu de pre et textarea octet pour octet, parce que leurs espaces sont rendues. Il conserve une espace unique entre deux éléments en ligne, parce que la supprimer collerait deux mots à l'écran. Et il ne touche pas à un attribut entre guillemets, si bien que title="a > b" survit intact au lieu d'être coupé au chevron. Ces trois comportements ont été vérifiés directement et tiennent tous les trois.
Il a tout de même un angle mort, et c'est justement celui que son propre commentaire prétend avoir fermé. Deux boutons séparés par une espace — <div><button>A</button> <button>B</button></div> — ressortent du minifieur en <button>A</button><button>B</button>. Les boutons sont en inline-block : cette espace est donc dessinée, et l'écart entre les deux boutons disparaît. La règle appliquée est que l'espace entre deux balises de bloc est invisible, et sa liste d'éléments en ligne contient a, b, span, code et une vingtaine d'autres, mais pas button, ni select, ni une image dans un lien. Vérifie toute rangée de boutons après minification.
Cinq entrées que ce minifieur CSS traite mal
La page css-minifier tient en cinq expressions régulières : supprimer les commentaires, réduire les suites d'espaces à une seule, retirer les espaces autour d'un jeu de caractères de ponctuation, supprimer un point-virgule avant une accolade fermante, rogner. C'est suffisant pour une feuille de style que tu as écrite il y a une heure, et insuffisant pour tout le reste, parce qu'une expression régulière ne distingue pas la structure du contenu.
Le premier échec est le grave. CSS Values and Units Level 3 précise, dans la syntaxe de calc(), qu'une espace est obligatoire de part et d'autre des opérateurs + et -. La liste de ponctuation contient ici le +, donc calc(100% + 16px) ressort en calc(100%+16px) et la déclaration entière devient invalide : le navigateur la jette et retombe sur ce qui existait avant. Comme le - n'est pas dans la liste, calc(100% - 16px) survit intact, ce qui est pire — la moitié de tes expressions calc fonctionnent, l'autre moitié disparaît en silence. Ce n'est pas un cas inventé. Le fichier apps/web/components/app/app-shell.module.css de ce dépôt contient calc(74px + env(safe-area-inset-bottom)), la marge qui tient la barre d'onglets mobile à l'écart de l'indicateur d'accueil. Passe-le dans cet outil et cette marge a disparu.
Les quatre autres viennent de la même racine : les chaînes et les data-URI sont du contenu, et les passes les traitent comme de la structure. content: "a; b" devient content:"a;b", parce que le point-virgule est dans la liste de ponctuation. content: "{ }" devient content:"{}". a[title="hello, world"] devient a[title="hello,world"] et le sélecteur cesse de correspondre. Une feuille de style dont la chaîne content contient les caractères qui ouvrent et ferment un commentaire CSS — content: "/* not a comment */" — ressort en content:"", la chaîne vidée. Et une image de fond écrite en data-URI qui contient par hasard la même séquence de deux caractères perd tout ce qu'il y a entre : url("data:image/svg+xml,...%3E/*x*/%3C...") arrive avec le milieu supprimé et l'image morte.
Deux choses qu'il ne casse pas, pour l'équilibre. Les propriétés personnalisées survivent : --shadow: 0 2px 8px rgba(0, 0, 0, 0.1) ressort en --shadow:0 2px 8px rgba(0,0,0,0.1), soit la même valeur. Les requêtes média survivent aussi : @media screen and (min-width: 600px) devient @media screen and (min-width:600px), toujours valide, et la syntaxe d'intervalle moderne @media (400px <= width <= 700px) reste intacte, parce que <= n'est pas dans la liste de ponctuation.
Deux minifieurs sur le même site, et le sûr pèse 2 octets de plus
La page css-compressor utilise un autre moteur. Au lieu de reconnaître des motifs, il parcourt le fichier caractère par caractère et marque chacun comme structure ou littéral : tout ce qui se trouve dans une chaîne, un commentaire ou une paire de parenthèses est littéral, et aucune transformation n'a le droit d'y toucher. C'est ce seul indicateur qui préserve un data-URI, une expression calc() et les décimales d'un rgba().
Tout l'intérêt de l'approche naïve était censé être sa compacité. Elle ne l'est pas. Les deux ont tourné sur les trois mêmes feuilles de style réelles. Sur app-shell.module.css, 22 746 octets en entrée, la version à expressions régulières a produit 19 278 octets et l'analyseur 19 280 — 2 octets d'écart, et en gzip l'analyseur était même plus petit d'un octet, 4 191 contre 4 192. Sur admin.css l'écart était de 1 octet brut et 2 octets gzippés. Sur globals.css, de 8 octets bruts. Huit octets, sur un fichier où la version sûre conserve l'espace dans @media (min-width: 600px) et dans rgba(0, 0, 0, 0.1). Il n'y a aucun argument de taille en faveur de la version à expressions régulières ; c'est simplement celle qui détruit parfois le fichier.
Le SVG est l'exception, et il a son propre bug
Tout ce qui précède dit que l'argument du poids en faveur de la minification est faible. Le SVG est là où il est fort, parce que le poids d'un SVG exporté n'est pas fait d'espaces. Un petit dessin enregistré depuis un éditeur vectoriel transporte une déclaration XML, un commentaire de l'éditeur, un titre, une description, un bloc de métadonnées RDF, une vue nommée avec le dernier niveau de zoom, deux espaces de noms d'éditeur, une transformation matricielle identité, une épaisseur de trait et une opacité fixées à leur valeur par défaut, et des coordonnées écrites à sept décimales. Passe un tel fichier — 1 071 octets — dans svg-optimizer et il ressort à 256 octets, 76,1 % en moins. Gzippé : 603 puis 207, 65,7 % en moins. Ce gain est réel parce que la matière retirée est du texte unique, et le texte unique est précisément ce dont un compresseur ne peut rien faire.
Cette même exécution a fait apparaître un défaut à connaître avant de s'en servir. Les couleurs traversent deux étapes dans le mauvais ordre : elles sont d'abord raccourcies, puis remises à la passe d'arrondi des nombres, qui lit les chiffres hexadécimaux comme des nombres. stroke="#000000" est raccourci en #000 puis arrondi en #0. black devient #0. red devient #f0. Et comme le motif numérique accepte la notation scientifique, une couleur hexadécimale dont les chiffres encadrent un e explose : #e5e7eb ressort en #e50000000eb, #1e293b en #1e+293b, #0e7490 en #0. La même passe réécrit url(#g-0010) en url(#g-10) tout en laissant id="g-0010" intact, si bien que le dégradé visé disparaît. Tout cela a été reproduit dans un vrai navigateur, avec les réglages par défaut. Désactiver l'option d'arrondi des nombres évite tous ces cas, au prix de quelques octets de précision.
Deux autres points sur le même outil. Il retire title et desc au titre des métadonnées d'éditeur — or ce sont les deux éléments qu'un lecteur d'écran annonce pour un SVG, si bien qu'une icône accessible cesse de l'être. Et son contrôle du balisage mal formé, lui, est du genre soigneux : un navigateur signale une erreur XML en greffant un élément nommé parsererror, si bien que chercher ce seul nom refuserait tout dessin valide qui en porte un. L'outil interroge donc le moteur : une fois par session, il analyse quelque chose de délibérément cassé, lit l'espace de noms du marqueur qui revient, et ne regarde plus que là. Un dessin qui contient un élément parsererror s'optimise normalement ; une balise non fermée reste refusée.
| Fichier | Original, brut / gzip | Espaces seules, gain gzip | Commentaires seuls, gain gzip |
|---|---|---|---|
| Composant de carte écrit à la main | 1 612 / 659 | 48 octets | 57 octets |
| app-shell.module.css (dense, peu commenté) | 22 746 / 5 661 | 103 octets | 1 358 octets |
| globals.css (très commenté) | 7 148 / 3 140 | 104 octets | 2 420 octets |
| admin.css | 4 767 / 1 855 | 147 octets | 1 042 octets |
| SVG exporté d'un éditeur, optimiseur complet | 1 071 / 603 | Métadonnées, pas espaces | 396 octets, 65,7 % |
Questions fréquentes
- Minifier le CSS vaut-il encore le coup si le serveur gzippe tout ?
- Oui, mais pour les commentaires, pas pour les espaces. Sur les quatre fichiers mesurés ici, retirer toutes les espaces et retours à la ligne a fait gagner 48, 103, 104 et 147 octets gzippés — une centaine d'octets chacun, que le fichier fasse 1,6 ko ou 22 ko, parce que gzip encode l'indentation répétée quasi gratuitement. Retirer les commentaires a fait gagner 57, 1 358, 2 420 et 1 042 octets gzippés sur les mêmes fichiers. Si ta feuille de style est documentée, les commentaires sont tout le gain ; sinon, la minifier te rapportera environ un dixième de kilo-octet et l'effort serait mieux placé dans une passe de suppression du CSS inutilisé. Ce à quoi la minification sert vraiment, dans une chaîne de compilation, c'est qu'elle est livrée avec les passes qui comptent : retirer les règles qu'aucun élément de la page n'utilise, fusionner les déclarations en double, raccourcir couleurs et unités.
- Ma mise en page a cassé après minification. Où regarder en premier ?
- Cherche calc( dans le fichier minifié et lis-les tous. Si l'un contient un plus sans espaces autour — calc(100%+16px) — cette déclaration est invalide et le navigateur l'ignore. Le CSS exige une espace de part et d'autre de + et - dans calc(), et un minifieur à expressions régulières qui resserre la ponctuation la supprime. Ensuite, cherche content: ainsi que tout sélecteur d'attribut contenant une virgule ou un point-virgule, parce qu'un minifieur naïf modifie l'intérieur des chaînes. Regarde ensuite les data-URI : si l'un contenait les deux caractères qui ouvrent un commentaire CSS puis, plus loin, les deux qui le ferment, tout ce qui se trouvait entre a été retiré. Enfin, compare le nombre de règles avant et après ; s'il a baissé, c'est du structurel qui a disparu, pas de l'espace.
- Dois-je embellir un fichier minifié que je n'ai pas écrit, avant de le modifier ?
- Oui, et c'est l'usage honnête d'un embellisseur. Reformater ne change que les espaces : cela ne peut pas altérer le comportement, et cela transforme un fichier d'une seule ligne en quelque chose qu'un diff sait décrire. Deux réserves. D'abord, un fichier embelli n'est pas automatiquement un fichier source — si l'original était généré depuis Sass, TypeScript ou une bibliothèque de composants, modifier la sortie signifie que ta modification disparaît à la compilation suivante. Ensuite, embellir puis reminifier n'est pas toujours l'identité : sur le moteur HTML testé ici, un aller-retour ajoute une espace de part et d'autre du texte de chaque élément non en ligne, faisant passer une page de 133 octets à 145 puis se stabilisant. Sans effet dans le navigateur, mais ne t'attends pas à retrouver un fichier identique à l'octet.
- Pourquoi l'optimiseur SVG fait-il gagner tellement plus que le minifieur CSS ?
- Parce qu'il retire une matière différente. Un minifieur CSS retire des espaces et des commentaires ; un compresseur gère déjà les espaces, donc seuls les commentaires comptent. Un optimiseur SVG retire des métadonnées d'éditeur, des attributs par défaut, des groupes vides et des décimales superflues — autant de texte unique qu'un compresseur ne peut pas replier. Dans le fichier mesuré ici, 1 071 octets sont devenus 256 en brut, et 603 octets gzippés sont devenus 207, une baisse de 65,7 % qui a survécu presque intacte à la compression. La leçon se généralise : tout minifieur qui se contente de reformater te décevra après gzip, et tout minifieur qui supprime du contenu ne te décevra pas. C'est aussi pourquoi la suppression de contenu est la partie à vérifier.
- Brotli diffère-t-il assez de gzip pour changer la réponse ?
- Non, elle la renforce légèrement. La feuille de style de carte s'est comprimée à 527 octets en Brotli contre 659 en gzip, et minifiée elle est descendue à 451 contre 555. Le gain absolu de la minification était de 76 octets en Brotli et de 104 en gzip : un meilleur compresseur laisse moins à retirer au minifieur, exactement comme on s'y attend, puisque les deux retirent la même redondance. Donc si ton hébergeur sert du Brotli — la plupart des CDN le font — l'argument en faveur de la minification des espaces est encore plus faible, et celui en faveur du retrait des commentaires est inchangé, parce qu'un commentaire est du texte unique quel que soit l'algorithme.
Articles qui pourraient t'intéresser
Tous les guides →Outils similaires
Ces chiffres viennent de l'exécution de ces outils sur de vrais fichiers, puis de la compression du résultat, pas d'une promesse d'éditeur. Le poids dépend entièrement du fichier : une feuille de style écrite avec de longs commentaires ne se comprime pas comme une feuille sans commentaires, et tes chiffres ne seront pas les nôtres. Les minifieurs ne se valent pas non plus — deux outils de ce site divergent sur la même entrée — alors traite toute sortie minifiée comme du code neuf, à relire avant mise en ligne. Garde l'original lisible dans le gestionnaire de versions, minifie à la compilation, et vérifie la page dans un navigateur avant de publier.
Sources
- W3C — CSS Values and Units Module Level 3, section 8.1.1 — the syntax of calc(), which states that white space is required on both sides of the + and - operators (the * and / operators may be used without it)
- W3C — CSS Syntax Module Level 3 — the tokenizer: how a string token, a comment and a url() token are recognised, and why a transform that does not run the tokenizer cannot tell a semicolon in a string from a declaration terminator
- IETF — RFC 1952, GZIP file format specification version 4.3 — the DEFLATE-based format used for the Content-Encoding: gzip of every stylesheet measured here, and the back-reference mechanism that makes repeated indentation nearly free
- W3C — Scalable Vector Graphics (SVG) 2 — the title and desc elements and their role in accessible names and descriptions, which is why an optimiser that strips them as editor metadata changes what a screen reader announces
Tu as repéré une erreur dans cet article ?