Pourquoi CSS suffit (presque) en 2026
Pendant des années, nous avons écrit du JavaScript pour des choses qui relèvent purement de la présentation : adapter un composant à la largeur de son parent, styliser un champ quand un autre est vide, ou calculer des variantes de couleur cohérentes. En 2026, trois fonctionnalités stables dans tous les navigateurs récents — les container queries, le sélecteur :has() et l’espace colorimétrique oklch() — rendent une bonne partie de ce code obsolète.
L’objectif de cet article est concret : construire une carte produit réutilisable qui s’adapte à son contexte, réagit à l’état de son contenu et utilise une palette cohérente, le tout sans une seule ligne de JavaScript. Suivez les étapes, copiez le code, adaptez-le à votre projet.
1. Container queries : le responsive par composant
Les media queries interrogent la fenêtre du navigateur. Le problème : un même composant peut vivre dans une barre latérale étroite ou dans une grille large sur la même page. Avec les container queries, on interroge la largeur du conteneur parent, pas celle de l’écran. Le composant devient enfin vraiment autonome.
La mécanique tient en deux temps : on déclare un élément comme contexte de confinement avec container-type, puis on écrit des règles @container dans ses descendants.
/* Le parent devient un contexte de confinement */
.grille-produits article {
container-type: inline-size;
container-name: carte;
}
/* La carte s'empile par défaut (mobile-first) */
.carte-produit {
display: grid;
gap: 1rem;
}
/* Dès que le CONTENEUR dépasse 30rem, on passe en deux colonnes */
@container carte (min-width: 30rem) {
.carte-produit {
grid-template-columns: 8rem 1fr;
align-items: start;
}
}
Résultat : la même carte affiche une mise en page verticale dans une colonne étroite et horizontale dans une zone large, automatiquement. Vous n’avez plus besoin de classes de variante (carte--compacte, carte--large) ni de logique JavaScript pour décider laquelle appliquer.
Bonus : les unités de conteneur
Les unités cqi (inline) et cqb (block) dimensionnent relativement au conteneur. Une typographie fluide par composant devient triviale :
.carte-produit h3 {
font-size: clamp(1rem, 4cqi, 1.5rem);
}
2. :has(), le sélecteur parent tant attendu
Historiquement, CSS ne savait styliser que vers le bas : un parent influence ses enfants, jamais l’inverse. :has() renverse la logique. On sélectionne un élément en fonction de ce qu’il contient. C’est le fameux « sélecteur parent » qu’on réclamait depuis quinze ans.
Quelques cas d’usage qui supprimaient autrefois du JavaScript :
- Mettre en valeur une carte qui contient un badge « rupture de stock ».
- Ajuster un formulaire selon la valeur d’une case à cocher, sans écouteur d’événement.
- Adapter une grille selon le nombre d’éléments présents.
/* Une carte sans image bascule en pleine largeur */
.carte-produit:has(.illustration[hidden]) {
grid-template-columns: 1fr;
}
/* Griser une carte en rupture de stock */
.carte-produit:has([data-stock="0"]) {
opacity: 0.55;
filter: grayscale(1);
}
/* Réagir à un champ : signaler un mot de passe trop court */
.champ:has(input:user-invalid) .message-erreur {
display: block;
}
Notez que :has() se combine avec :user-invalid, qui ne se déclenche qu’après une interaction réelle — bien plus agréable que l’ancien :invalid qui rougissait les champs avant même la saisie.
3. OKLCH : des couleurs qu’on peut enfin raisonner
En hexadécimal ou en hsl(), faire varier la luminosité d’une couleur donne des résultats imprévisibles : un jaune et un bleu de même « luminosité » HSL n’ont pas du tout le même éclat perçu. oklch() repose sur un modèle perceptuel. Ses trois composantes sont lisibles : L (luminosité de 0 à 1), C (chroma, l’intensité) et H (teinte en degrés).
L’intérêt majeur : fixez L et C, faites tourner H, et vous obtenez une palette dont toutes les couleurs ont la même intensité perçue. Idéal pour des thèmes cohérents.
:root {
/* Une teinte de marque, déclinée proprement */
--brand-h: 255;
--brand: oklch(0.62 0.19 var(--brand-h));
--brand-clair: oklch(0.88 0.07 var(--brand-h));
--brand-fonce: oklch(0.42 0.16 var(--brand-h));
/* Couleur d'accent : même L et C, teinte opposée */
--accent: oklch(0.62 0.19 calc(var(--brand-h) + 180));
}
.badge-promo {
background: var(--brand-clair);
color: var(--brand-fonce);
}
OKLCH gère aussi les écrans à large gamut (P3) et accepte une syntaxe de transparence : oklch(0.62 0.19 255 / 0.5).
Conseil clé : raisonnez vos couleurs en variables OKLCH dès le départ, en isolant la teinte (H) dans une variable. Changer toute l’identité visuelle d’un site se résume alors à modifier une seule valeur, et vos déclinaisons restent automatiquement équilibrées.
Le piège fréquent à éviter
Le piège numéro un avec les container queries est l’effondrement de mise en page. Quand vous déclarez container-type: inline-size, le navigateur cesse de calculer la hauteur de cet élément à partir de son contenu de la manière habituelle dans certains contextes, et surtout un conteneur ne peut pas s’interroger lui-même. Si vous écrivez vos règles @container en visant l’élément qui porte container-type, elles ne s’appliqueront jamais. La règle doit cibler un descendant du conteneur. Pensez « le parent est le conteneur, l’enfant est mesuré ».
Second piège, plus discret : :has() peut devenir coûteux s’il est appliqué très haut dans l’arbre (par exemple sur body:has(...)) avec des sélecteurs larges. Gardez-le ciblé sur des sous-arbres précis.
Récapitulatif
Avec ces trois piliers, vous écrivez des interfaces plus robustes et bien moins de JavaScript :
- Container queries : des composants réellement autonomes, responsives selon leur contexte et non l’écran.
- :has() : du style conditionnel basé sur le contenu et l’état, sans écouteurs d’événements.
- OKLCH : des palettes cohérentes, prévisibles et accessibles, pilotées par quelques variables.
Le mot d’ordre de 2026 est simple : avant d’ajouter un script, demandez-vous si le CSS ne le fait pas déjà. La réponse est de plus en plus souvent oui. Ouvrez votre éditeur, reprenez la carte produit ci-dessus, et voyez par vous-même tout ce qui disparaît de votre fichier JavaScript.
Pour aller plus loin
- Git et GitHub : prendre de bonnes habitudes — versionner proprement votre code dès le départ.
- Intégrer un LLM dans votre application — appeler un modèle, streaming, coûts et erreurs.
Aucun commentaire pour l'instant — lancez la discussion !