--- # vim: spell spelllang=fr title: 'Adopter un CSS moderne' slug: '008-adopter-css-moderne' date: '2025-07-06T14:29:26+02:00' draft: false categories: - dev tags: - CSS summary: Exploration de développements récents de CSS dont j'étais passé à côté. description: | L'article explore les récentes évolutions du CSS, telles que l'imbrication des règles, les variables CSS, et l'utilisation de CSS sans classes, qui permettent une écriture plus propre et plus efficace des feuilles de style. Il mentionne également des fonctionnalités futures comme les mixins CSS, les propriétés personnalisées CSS, et les portées CSS, qui promettent d'améliorer encore davantage la manière de styliser les interfaces utilisateur. --- Je suis récemment tombé sur une note dans une page de [Plain Vanilla] dans laquelle j'ai appris que le CSS imbriqué est valide. C'est possible depuis assez longtemps, mais je ne le savais pas (je suis assez en retard dans mon lecteur RSS). Cela m'a permis de rattraper certaines des récentes évolutions du CSS. [Plain Vanilla]: https://plainvanillaweb.com/pages/styling.html ## CSS imbriqué L'imbrication des règles CSS est l'une des principales raisons pour lesquelles j'ai utilisé [SASS] pendant 15 ans. J'ai toujours préféré écrire des règles imbriquées pour regrouper des unités cohérentes de CSS. Par exemple, ```scss a { text-decoration: none; &:hover { text-decoration: underline; } } header { nav { ul { list-style: none; li { text-align: center; } } } } ``` a plus de sens pour moi que ```css a { text-decoration: none; } a:hover { text-decoration: underline; } header nav ul { list-style: none; } header nav ul li { text-align: center; } ``` Il y a plusieurs raisons à ça : * C'est plus facile à lire car les sélecteurs sont plus courts et la hiérarchie est plus facile à comprendre ; * Je peux déplacer un groupe de sélecteurs sans risquer d'oublier une déclaration ; * Je peux utiliser le repliement de code basé sur l'indentation de mon IDE pour fermer un groupe et naviguer dans de longs fichiers CSS. Depuis que le module [CSS Nesting] est disponible de manière générale et est [supporté par 90% des utilisateurs], il peut être utilisé pour écrire du CSS imbriqué. Donc maintenant, c'est du CSS valide : ```css a { text-decoration: none; &:hover { text-decoration: underline; } } header { nav { ul { list-style: none; li { text-align: center; } } } } ``` Le fichier [CSS de ce site] a été réécrit en utilisant le CSS imbriqué. [SASS]: https://sass-lang.com [CSS Nesting]: https://drafts.csswg.org/css-nesting/ [supporté par 90% des utilisateurs]: https://caniuse.com/css-nesting [CSS de ce site]: https://bcarlin.net/static/css/bcarlin.css ## Variables CSS Pour moi, les variables sont essentielles pour assurer une interface utilisateur cohérente. Elles permettent de réutiliser des couleurs, des tailles, des espacements, etc. C'est aussi une raison pour laquelle j'ai utilisé SASS. Cela m'a permis d'écrire du CSS avec des variables réutilisables : ```scss $color-error: red; $color-success: green; label { &.error { color: $color-error; } &.success { color: $color-success; } } .notification { &.error { background-color: $color-error; } &.success { background-color: $color-success; } } ``` J'ai manqué la publication du module [CSS Custom Properties for Cascading Variables Module Level 1] de 2017, qui m'a permis d'écrire la même chose en CSS pur : ```css :root { --color-error: red; --color-success: green; } label { &.error { color: var(--color-error); } &.success { color: var(--color-success); } } .notification { &.error { background-color: var(--color-error); } &.success { background-color: var(--color-success); } } ``` [CSS Custom Properties for Cascading Variables Module Level 1]: https://www.w3.org/TR/css-variables/ ## CSS Sans Classes Peut-être que je vais à contre-courant ici, , compte tenu de la popularité des frameworks CSS « utilitaires » comme [TailwindCSS]. Ce point n'est pas vraiment une fonctionnalité CSS en soi, mais c'est une façon d'écrire du CSS, où le HTML sémantiquement correct est automatiquement mis en forme correctement. Dans une certaine mesure, il est cependant soutenu par certains [Sélecteurs CSS Niveau 4] qui sont maintenant largement implémentés dans les navigateurs, tels que `:has`, `:is`, `:where`, `:not`, etc. J'utilisais habituellement [BootstrapCSS] dans mes projets parce qu'il est complet et facile à utiliser, mais je n'ai jamais aimé la façon dont il imposait une structure CSS relativement lourde. Pour ce site, je cherchais quelque chose de plus léger et je suis tombé sur [PicoCSS] qui a mis en forme 90% de mon site sans changer quoi que ce soit à mes modèles. J'avais déjà une structure HTML de base sémantiquement significative : ```html

Titre de la Page

``` Et j'aime vraiment la façon dont cela fonctionne : le contenu est mis en forme en fonction de son balisage sémantique, et non en fonction d'une structure HTML imposée. Par exemple, voici le [composant Modal de Bootstrap] : ```html ``` Voici le [composant Modal de Tailwind Plus] : ```html
``` Comparez-les avec le [composant Modal de PicoCSS] : ```html

Titre de la fenêtre

Corps de la fenêtre
``` Cela fait une énorme différence en termes de simplicité, de lisibilité et d'accessibilité (notez que les attributs ARIA sont rendus inutiles car le balisage sémantique porte déjà cette information). [TailwindCSS]: https://tailwindcss.com [Sélecteurs CSS Niveau 4]: https://drafts.csswg.org/selectors-4/ [BootstrapCSS]: https://getbootstrap.com [PicoCSS]: https://picocss.com [composant Modal de Bootstrap]: https://getbootstrap.com/docs/4.3/components/modal/#live-demo [composant Modal de Tailwind Plus]: https://tailwindcss.com/plus/ui-blocks/application-ui/overlays/modal-dialogs [composant Modal de PicoCSS]: https://picocss.com/docs/modal ## `@import` pour diviser les fichiers CSS Un dernièr point pour lequel j'aimais utiliser SASS était la possibilité de diviser les fichiers CSS en fichiers plus petits pour les rendre plus faciles à comprendre. Par exemple : ```scss @use 'reset'; @use 'typography'; @use 'layout'; @use 'content'; ``` Avec le module [CSS Cascading and Inheritance Level 5], CSS a cela nativement : ```css @import url('reset.css'); @import url('typography.css'); @import url('layout.css'); @import url('content.css'); ``` De ma compréhension, les fichiers CSS `@import`és sont téléchargés en parallèle, ce qui réduit le coût d'avoir plusieurs fichiers à télécharger. Les règles CSS `@import` ont même l'avantage d'être conditionnelles. Par exemple : ```css @import url("light.css") only screen and (prefers-color-scheme: light); @import url('dark.css') only screen and (prefers-color-scheme: dark); ``` [CSS Cascading and Inheritance Level 5]: https://drafts.csswg.org/css-cascade-5/ ## Les évolutions que j'attends avec impatience Voici quelques spécifications que j'ai hâte d'utiliser. Je ne les utilise pas encore en raison du support des navigateurs ou parce que je n'en ai pas encore eu besoin. Mais je suis impatient de les essayer. ### Mixins CSS Les Mixins CSS sont également une fonctionnalité majeure de SASS, et favorisent un code CSS plus propre et plus réutilisable. CSS les aura avec le [Module des fonctions et mixins CSS], qui est encore un brouillon, et dans lequel les mixins ne sont pas encore spécifiés. En attendant, voici un exemple du [Guide des Mixins SASS] : ```scss @mixin rtl($property, $ltr-value, $rtl-value) { #{$property}: $ltr-value; [dir=rtl] & { #{$property}: $rtl-value; } } .sidebar { @include rtl(float, left, right); } ``` Bien que dans certains cas, cela puisse être facilement remplacé par des variables CSS : ```css :root { --sidebar-float: left; } [dir=rtl] { --sidebar-float: right; } .sidebar { float: var(--sidebar-float); } ``` [Guide des Mixins SASS]: https://sass-lang.com/documentation/at-rules/mixin/#arguments [Module des fonctions et mixins CSS]: https://www.w3.org/TR/2025/WD-css-mixins-1-20250515/ ### Propriétés Personnalisées CSS Celle-ci est une petite fonctionnalité sympa du module [CSS Properties and Values API Level 1] qui étend les variables CSS. Elles permettent de définir le type, la valeur initiale et la règle d'héritage d'une variable personnalisée. Par exemple : ```css {linenos=true} @property --my-color { syntax: ""; inherits: false; initial-value: black; } .primary { --my-color: red; } .secondary { --my-color: 10px; } button { background-color: var(--my-color); color: white; } ``` Ici, la définition de `--my-color` à la ligne 12 n'est pas valide (c'est une longueur et non une couleur). Comme la valeur de la propriété n'est pas héritée d'un parent, la valeur initiale sera utilisée : un `