Nouveau blog -- partie 2 : CSS
Si la première partie traitait de HTML, si vous m'avez suivi la seconde partie traite de CSS !
Je me doute que vous A-DO-REZ CSS de tout votre être ! 🥸 Et pourtant !
Je ne me dirais jamais ultra top expert CSS, mais je sais faire du CSS, je sais faire dès trucs que je trouve assez propre avec peu de ligne de CSS, en comprenant ce que je fais et en faisant majoritairement du HTML sémantique et avec peu de classe ! Mais c'est vrai que CSS demande un apprentissage qui peut être frustrant… Mais passons…
Je vous montre quelques trucs que j'ai faits qui sont à mon sens trop peu utilisé !
HTML Sémantique🔗
Ce point rentrait presque plus dans la première partie mais je trouve que ça a plus d'impact au niveau du CSS au final : j'ai essayé au maximum de faire du HTML Sémantique. C'est à dire éviter au maximum les <span> et <div>.
Pour vous donner une idée, j'ai une seule balise <div> par page comme celle que vous lisez, et une balise <span> par tag mis sur l'article parce que je n'ai pas trouvé de meilleure balise pour représenter ça. Sinon j'utilise par exemples des conteneurs <section> qui indique clairement aux lecteurs d'écrans que j'ai des blocs logiques dans ma page (j'en ai 3 dans chaque page actuellement), ou simplement <article> / <header> / <main> / <footer> qui ont des sémantiques très clairement définies.
Globalement j'ai finalement assez peu de balise superflue où présente uniquement pour le style. J'ai aussi assez peu de classe, car la plupart du temps je n'en ai pas besoin pour cibler des éléments, en tout cas clairement je n'ai pas de classe sur chaque élément. L'idée derrière c'est que mon HTML est plutôt clean en lui-même et reste très lisible même par un humain.
Par contre ça implique que j'ai des fichiers de styles bien pensées et qui viennent tout gérer en CSS moderne. Je précise moderne, car c'est vrai que c'est devenu plus facile aujourd'hui de faire du HTML sémantique avec un style reposant peu sur des <div> et des classes, là où il y a une dizaine d'années c'était presque impossible… Mais on est en 2026, il faut utiliser ce que nous offre le navigateur au maximum pour travailler le moins possible, car c'est plus accessible et plus performant !
CSS Reset🔗
Pour moi la première chose à faire c'est mettre en place un ensemble de "reset". L'idée c'est de forcer de base un certain style/comportement de base qui va permettre de travailler confortablement.
Le mien est assez court, et comprend :
*,
*::before,
*::after {
box-sizing: border-box;
}CSS
Pour s'assurer de fonctionner de base partout en border-box, c'est à dire que la bordure d'un élément fait partie intégrante de la taille de l'élément. Donc si je définis un élément avec une largeur de 100px et une bordure de 2px, mon élément mesurera 100px de largeur. Par défaut (content-box), mon élément mesurerait 104px de largeur.
Je trouve ça plus naturel dans la majorité des cas, mais dans certains cas je sais que je peux passer en content-box si c'est plus simple pour moi.
body {
margin: unset;
}CSS
Pour s'assurer que le body de la page n'a aucune marge, et donc que peu importe le layout qu'on choisira de mettre en place il prendra toute la place à l'écran. À une époque je mettais html, body { ... } pour éviter d'éventuelle marge sur l'élément <html> aussi (parce que oui on trouvait parfois de la marge ici aussi, sous d'ailleurs quand on utilisait un framework CSS ce qui n'est pas mon cas sur le blog).
button,
input,
textarea,
select {
font: inherit;
}CSS
Pour s'assurer qu'on a bien la même police d'écriture partout, car parfois les <bouton>, <input>, <textarea> et <select> utilise une autre police et ça complique le style.
img,
picture,
svg,
canvas {
display: block;
max-inline-size: 100%;
block-size: auto;
}CSS
Pour les images et canvas soient affichés comme des éléments block (et non inline comme par défaut) pour facilité le style (dimensions et position surtout).
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}CSS
Ici c'est plus subtil, et c'est les seuls !important que j'ai. On va s'assurer de réduire au maximum les animations affichées pour les personnes qui demande explicitement via leur navigateur à avoir des animations réduites. C'est un paramètre qu'on peut activer au niveau du système d'exploitation et qui rend plus agréable la navigation pour certains utilisateurs qui sont gênés par les animations.
Layers🔗
Feature assez peu connu j'ai l'impression, pourtant c'est extrêmement pratique !
L'idée des layers est très simple : hiérarchiser des ensembles de style. Vous allez pouvoir dire que tel partie du style doit être appliqué en premier, ensuite tel autre partie passe ensuite et peu contredire directement la première partie, et ainsi de suite.
En gros : vous n'avez plus besoin de !important ou de jouer sur des sélecteurs complexe pour surcharger le style de vos éléments. 🤩
Et c'est même pas compliqué à utiliser !
@layer reset, base, layout, page;CSS
Cette ligne s'ajoute de préférence dans le premier fichier de style que vous allez charger, pour que le navigateur sache au plus vite comment organiser les styles. Elle va permettre de définir tous nos groupes et l'ordre de priorité. Techniquement cette ligne est optionnelle mais si on ne l'ajoute pas, c'est l'ordre de déclaration des styles de layer qui va définir l'ordre d'application (comme d'habitude avec le CSS, l'ordre est important). Donc ici tout le style de la couche reset va s'appliquer, puis le style base, puis le style layout, puis enfin page.
@layer reset {
// tout le code de reset présenté avant
}
@layer base {
// tout le style de base
}
@layer layout {
// tout le style de layout
}
@layer page {
// tout le style de la page
}CSS
Ensuite on va entourer chaque portion de style avec une section @layer nom-layer {} et faire comme d'habitude. Bien sûr : vous pouvez définir les sections layer dans plusieurs fichiers différents, vous pouvez aussi définir les layers en plusieurs parties (par exemple avoir plusieurs fichiers css qui vont contenir chacun une section page).
La priorité des sélecteurs se fera à l'intérieur d'une couche mais pas entre couche.
Ça veut dire que si vous avez ce style
@layer base, page;
a {
color: blue;
}
body > p.alert a {
color: red;
}
@layer page {
a {
text-decoration: blue underline wavy 2px;
}
}
@layer base {
body > p.alert a {
text-decoration: red underline 2px;
}
}CSS
appliqué à ce contenu
<html>
<body>
<p class="alert"><a href="#">Inside p.alert</a></p>
<p><a href="#">another link</a></p>
</body>
</html>HTML
Vous aurez ça qui va s'afficher :
Ce qui se passe :
- la première ligne indique que le style
basepasse avantpage; - ensuite on définit que tous les liens doivent être de couleur bleue, puis que ceux qui sont dans un paragraphe avec la classe
alertà la racine du body doivent être rouges, comme le second sélecteur est plus précis que le premier, c'est celui-ci qui sera pris en compte pour les liens concernés ; - ensuite on définit que dans la layer
pageles liens doivent être soulignés avec une vague bleue, puis dans la layerbaseon définit que les liens qui sont dans un paragraphealertà la racine du body doivent être soulignés en rouge, sauf la layerpageva surcharger le style de la layerbasedonc contrairement à la couleur du texte tous les liens sont soulignés avec une vague bleue ;
Vous pouvez jouer avec cet exemple ici : https://kuroidoruido.github.io/css-is-magic/layers/index.html
CSS Components et nesting🔗
Comme je pense tous les développeurs frontend ces dernières années : je travaille avec des composants, avec tous les bons et mauvais côtés que ça implique.
Mon blog ne déroge pas à la règle, même si tout se passe en CSS. Je me suis inspiré de pas mal de framework CSS existant, à commencer par picoCSS :
- passer au maximum par du HTML sémantique ;
- ajouter du style avec le moins de balise / classe superflue possible ;
- créer des composants qui s'auto-applique sur des éléments avec éventuellement des classes quand j'ai besoin ;
Un outil qui je trouve aide beaucoup c'est le CSS nesting. Personnellement c'était une des seules raisons qui faisaient que j'utilisais du SASS avant, depuis je m'en passe complètement.
Concrètement ?
article:not(.main) {
border: 1px solid gray;
}
article header h1 {
font-size: 3rem;
}
article main p {
font-size: 1rem;
}
article main a:hover {
text-decoration: blue underline 2px;
}CSS
peut aussi être écrit
article {
&:not(.main) {
border: 1px solid gray;
}
header {
h1 {
font-size: 3rem;
}
}
main {
p {
font-size: 1rem;
}
a:hover {
text-decoration: blue underline 2px;
}
}
}CSS
Et certes la seconde version est plus verbeuse (au sens où ça prend plus de ligne), mais clairement ça permet d'avoir toujours des sélecteurs plus précis à moindre effort, c'est facile de regrouper le style qui concerne un élément, on peut replier le style d'un élément d'un coup, on a pas besoin de répéter des parties de sélecteur pour garantir la priorité, etc.
Le nesting n'a pour moi quasiment que des avantages !
Custom Properties🔗
L'autre grosse raison d'utiliser SASS c'était les variables. On peut faire des calculs, on peut partager des valeurs un peu partout dans notre style, et éviter d'avoir 18 fois la même couleur bleue sauf à un endroit où on s'est trompé d'un caractère ou qu'on a changé le bleu en oubliant un endroit…
Les custom properties c'est globalement la réponse aux variables SASS mais nativement supporté par le navigateur et géré sans compilation, sans avoir d'import bizarre, de fichier avec des préfixes _ dont on ne comprenait pas toujours l'impact, etc.
Et qui dit custom properties, dit : on peut construire facilement des thèmes (j'y reviendrai plus loin) !
Les custom properties sont pensés pour fonctionner de manière très proche des propriétés classiques : elles sont hiérarchiques, suivent les mêmes précédences, peuvent être surchargés, etc.
Comme ça marche ?
:root {
--je-suis-une-variable-globale: #007bff;
}
article {
--je-suis-une-disponible-que-dans-les-articles: #ff7b00;
main {
color: var(--je-suis-une-variable-globale);
text-decoration: var(--je-suis-une-disponible-que-dans-les-articles) underline 2px;
}
}CSS
Une variable doit forcément être définie dans un contexte, pour avoir quelque chose de global, j'utilise le pseudo-sélecteur :root pour définir une couleur bleue, ensuite dans article je définis une autre variable pour une couleur orange, et je les utilise dans main.
C'est très simple à manipuler. Et on peut les utiliser pour produire des briques UI propres :
:root {
/* ATOMS */
--color--white: #ffffff;
--color--dark-gray: #333333;
/* ... */
/* MOLECULES */
--color--bg: var(--color--white);
--color--text: var(--color--dark-gray);
}
/* ... */
@layer base {
html {
background-color: var(--color--bg);
color: var(--color--text);
}
}CSS
Voilà c'est pas plus compliqué que ça. Ça fonctionne évidemment aussi avec les tailles, sur le blog j'ai par exemple 7 tailles différentes qui sont standardisées :
:root {
--size--quarter: 0.125rem;
--size--half: 0.25rem;
--size--1: 0.5rem;
--size--2: 1rem;
--size--3: 1.5rem;
--size--4: 2rem;
--size--5: 4rem;
}CSS
Peu importe le fichier de style, je pourrais utiliser les variables car la mise à disposition est gérée par le navigateur.
Note : On est obligé de commencer les noms de custom properties par
--mais ce sont mes conventions garder des-ensuite, j'ai aussi pris l'habitude de définir des sortes de contexte avec deux parties sur le nom séparé par--, ça me permet de m'y retrouver plus vite, mais ce n'est pas obligatoire.
Je peux vous montrer par exemple le style qui gère le bloc en haut des pages de cette série d'article :
nav[data-serie] {
--toc-series--margin-x: var(--size--5);
@media screen and (width < 50rem) {
--toc-series--margin-x: var(--size--2);
}
border: var(--size--quarter) solid var(--color--secondary);
border-radius: var(--size--1);
padding: var(--size--1) var(--size--4);
margin: 0 var(--toc-series--margin-x);
ul {
list-style-type: upper-roman;
}
}CSS
J'ai coupé le nesting mais sinon tout le reste est là : je commence par définir une variable propre au sommaire (toc = table of content), qui est surchargé pour gérer le responsive, ensuite je fais essentiellement des combinaisons de variables. De cette façon, visuellement on est plus uniforme et on peut plus facilement faire évoluer ces éléments.
Note : On voit aussi à nouveau l'apport du nesting pour regrouper tout le style dans un seul groupe de style. On voit aussi une certaine logique "composant" au final, avec chaque brique visuel qui est un groupe CSS.
Penser au responsive !🔗
On ne peut pas faire un site web grand public sans penser responsive et encore moins mobile. En France, on peut partir du principe qu'environ 50% du traffic web se fait sur mobile.
Pour moi c'était important que les gens qui me lisent puissent me lire dans des bonnes conditions, donc je voulais que peu importe votre taille d'écran, vous soyez à l'aise pour lire (si ce n'est pas le cas, n'hésitez pas à me contacter pour que je corrige les cas que j'aurais oubliés).
Pas vraiment de magie, je suis essentiellement passé par un break-point à 700px (en gros : je considère que la vue desktop c'est tous les écrans de plus 700px de large, et les mobiles en dessous de 700px). C'est clairement simpliste mais ça m'a l'air plutôt raisonnable comme découpe. Ensuite j'ai beaucoup joué avec des layouts flex ou grid en fonction du cas pour avoir un affichage qui tient la route, s'ajuste à la taille de l'écran sans devenir trop large (je pense à vous les utilisateurs d'écran ultra wide qui doivent parfois user votre nuque pour lire les lignes de texte trop longues…).
J'ai aussi un peu joué côté page article sur des largeurs d'écrans en nombre de caractère (par exemple : @media (width < 100ch)) pour pouvoir vraiment dimensionner le texte de manière cohérente.
Au final j'ai peu utilisé de media query, et beaucoup plus sur la flexibilité du layout pour s'adapter à votre écran.
J'ai aussi utilisé assez facilement les fonctions min() et max() qui sont quand même bien pratiques !
Par exemple :
:root {
--reponsive-index-max-width: min(100dvw, var(--cover--max-width))
}CSS
Ici la variable --reponsive-index-max-width va être définie à ̀var(--cover--max-width) uniquement si c'est plus petit que 100dvw (100% de la largeur dynamique du viewport) donc dit autrement : toute la largeur de la page sauf si largeur de la page est plus grande que var(--cover--max-width). C'est très simple, c'est super efficace, et c'est responsive !
Si j'ai une seule chose à conseiller : testez sur des mobiles physiques aussi. On se rend beaucoup mieux compte de la taille des choses, de comment on interagit avec les boutons, de si tout est bien lisible sur un vrai téléphone que sur un simulateur (même si on a vu des gros progrès, ce n'est pas parfait et on loupe pas mal de choses).
Double thème🔗
J'en ai parlé sur la partie HTML, évidemment que j'allais aussi en parler sur la partie CSS !
J'avais passé pas mal de temps à lire plein de choses sur le sujet, à me prendre la tête pour finalement gérer le sujet du thème clair / sombre super facilement avec des outils modernes de CSS.
Voilà tout le code qui concerne ma gestion de thème :
:root {
/* ATOMS */
--color--white: #ffffff;
--color--black: #121212;
--color--dark-gray: #333333;
--color--gray: #6c757d;
--color--light-gray: #e0e0e0;
--color--blue: #007bff;
--color--green: #28a745;
/* MOLECULES */
--color--bg: light-dark(var(--color--white), var(--color--black));
--color--text: light-dark(var(--color--dark-gray), var(--color--light-gray));
--color--primary: var(--color--blue);
--color--secondary: var(--color--gray);
--color--accent: var(--color--green);
--color--text-link: light-dark(var(--color--black), var(--color--white));
}CSS
J'ai d'abord défini toutes mes couleurs brutes (pour être honnête : merci Mistral pour le choix des couleurs), puis j'ai positionné ces couleurs sur des usages, en les combinants de sorte à définir mon thème. La fonction light-dark() étant assez magique pour ça, car il suffit de lui donne la couleur pour le thème clair et la couleur pour le thème sombre et la bonne couleur est choisie automatiquement et de manière réactive au changement de thème sans avoir rien de plus à faire !
Conclusion🔗
Même si j'ai parlé de style tout au long de cet article, j'ai fait en sorte que mon blog se charge relativement bien même si aucun fichier css ne s'affiche. Par exemple, j'ai dans le fichier html de ma page d'accueil ces lignes qui viennent masquer les images de base (c'est annulé dans le style principal dans la couche page via img { display: unset; }) :
<style>
@layer base {
img {
display: none;
}
}
</style>HTML
Toujours dans ma logique de progressive enhancement j'ai fait en sorte que le contenu soit le centre du blog, puis j'ai ajouté du style pour améliorer le style, l'affichage, apporter du confort (et me faire un peu plaisir au passage évidemment).
J'ai utilisé beaucoup de fonctionnalité moderne de CSS. Des fonctionnalités qu'on utilise pas assez à mon avis. Des fonctionnalités qu'on a tendance à ignorer quand on utilise massivement des frameworks ou des outils comme TailwindCSS car ça vous impose de raisonner local alors que le CSS est pensé pour raisonner global à mon sens…
La suite logique au CSS c'est le JavaScript et j'en ai fait un peu, juste ce qu'il faut. On se retrouve sur la partie 3 pour voir ça !
Crédit photo : Générée via Mistral AI avec le prompt suivant :
Une scène chaleureuse et immersive, inspirée par l’esthétique poétique de Studio Ghibli, représentant un atelier de couture high-tech en bois clair et vieilli, baigné d’une lumière dorée et tamisée, comme un après-midi d’automne. Au centre, un panda roux anthropomorphe (Firefox), vêtu d’une veste ample et confortable, est assis à une table de travail en bois, concentré sur la couture de styles CSS.
Autour de lui, des bobines de fil colorées (bleu électrique, orange, beige) flottent comme des variables CSS, et des morceaux de tissu représentent des feuilles de style. Le panda roux utilise une aiguille et du fil pour "coudre" des styles CSS sur une toile de HTML nu, symbolisant la mise en forme du contenu. Des ciseaux et des patrons de couture stylisés en balises CSS (
{ }) sont posés sur la table, tandis qu’un miroir magique montre le rendu final (thème light/dark) en reflet.En arrière-plan, une grande fenêtre donne sur une ville nocturne aux néons bleutés, reflétant des motifs de code binaire sur les murs. Une tasse de thé fumant et des feuilles d’érable flottent doucement dans l’air, ajoutant une touche magique à la scène.
À droite, en bas, le panda roux est légèrement tourné en 3/4 dos, lové sur un coussin, entouré d’un halo lumineux subtil. Il ne dépasse pas le tiers de la hauteur de l’image et observe son travail avec satisfaction.
L’ambiance est cosy, onirique et high-tech : les couleurs sont douces (beiges, bleus pâles, oranges chauds), avec des jeux de lumière tamisée dorée qui créent des ombres chaleureuses. Les détails sont soignés, avec des textures visibles (grain du bois, tissu, pelage du panda roux), et une lumière qui met en valeur les éléments tech et artisanaux. Le tout respire la sérénité et l’inspiration, comme un moment suspendu entre la magie et la technologie.""Une scène chaleureuse et immersive, inspirée par l’esthétique poétique de Studio Ghibli, représentant un atelier de couture high-tech en bois clair et vieilli, baigné d’une lumière dorée et tamisée, comme un après-midi d’automne. Au centre, un panda roux anthropomorphe (Firefox), vêtu d’une veste ample et confortable, est assis à une table de travail en bois, concentré sur la couture de styles CSS.
Autour de lui, des bobines de fil colorées (bleu électrique, orange, beige) flottent comme des variables CSS, et des morceaux de tissu représentent des feuilles de style. Le panda roux utilise une aiguille et du fil pour "coudre" des styles CSS sur une toile de HTML nu, symbolisant la mise en forme du contenu. Des ciseaux et des patrons de couture stylisés en balises CSS (
{ }) sont posés sur la table, tandis qu’un miroir magique montre le rendu final (thème light/dark) en reflet.En arrière-plan, une grande fenêtre donne sur une ville nocturne aux néons bleutés, reflétant des motifs de code binaire sur les murs. Une tasse de thé fumant et des feuilles d’érable flottent doucement dans l’air, ajoutant une touche magique à la scène.
À droite, en bas, le panda roux est légèrement tourné en 3/4 dos, lové sur un coussin, entouré d’un halo lumineux subtil. Il ne dépasse pas le tiers de la hauteur de l’image et observe son travail avec satisfaction.
L’ambiance est cosy, onirique et high-tech : les couleurs sont douces (beiges, bleus pâles, oranges chauds), avec des jeux de lumière tamisée dorée qui créent des ombres chaleureuses. Les détails sont soignés, avec des textures visibles (grain du bois, tissu, pelage du panda roux), et une lumière qui met en valeur les éléments tech et artisanaux. Le tout respire la sérénité et l’inspiration, comme un moment suspendu entre la magie et la technologie.