Fonctionnalités CSS Modernes Qui Ne Nécessitent Plus JavaScript
Pendant des années, les développeurs frontend ont eu recours à JavaScript pour gérer les patterns d’interface utilisateur interactifs. Les accordéons nécessitaient des gestionnaires de clics. Les infobulles requéraient des bibliothèques de positionnement. Les composants responsives exigeaient des observateurs de redimensionnement. Cette époque touche à sa fin.
Le CSS moderne gère désormais le styling avec état, les points de rupture au niveau des composants, les effets basés sur le défilement et les popovers natifs—le tout sans une seule ligne de JavaScript. Il ne s’agit pas de fonctionnalités expérimentales. Elles sont stables, largement supportées et prêtes pour la production en 2025.
Points Clés
- Le sélecteur CSS
:has()permet de styler les éléments parents en fonction de l’état de leurs enfants, éliminant le besoin de JavaScript pour le styling de validation de formulaires et les composants interactifs. - Les container queries permettent aux composants de répondre à la taille de leur conteneur plutôt qu’au viewport, remplaçant les resize observers JavaScript.
- Les animations pilotées par le défilement s’exécutent sur le thread du compositeur, offrant de meilleures performances que les alternatives basées sur Intersection Observer.
- L’API Popover et l’attribut
<details name="">fournissent des infobulles, menus et accordéons natifs et accessibles sans scripts personnalisés.
Le Sélecteur CSS :has() : La Sélection Parente Arrive Enfin
Le sélecteur CSS :has() résout un problème dont les développeurs se plaignent depuis des décennies : styler les éléments parents en fonction de l’état de leurs enfants.
Auparavant, basculer l’apparence d’une carte lorsque sa case à cocher était cochée nécessitait des écouteurs d’événements JavaScript. Désormais, CSS le gère directement :
.card:has(input:checked) {
border-color: blue;
}
Ce pattern élimine des catégories entières de JavaScript :
- Styling de validation de formulaires : Styler les conteneurs en fonction des entrées
:validou:invalid - Layouts pilotés par l’état : Modifier les grilles parentes lorsque les enfants sont vides ou présents
- Composants interactifs : Construire des onglets, accordéons et boutons à bascule en utilisant des inputs cachés et
:has()
Le sélecteur fonctionne sur tous les navigateurs majeurs. Pour le support des navigateurs plus anciens, encapsulez les styles dans @supports selector(:has(*)) et fournissez une expérience de base.
Container Queries CSS : Responsivité au Niveau des Composants
Les media queries répondent à la taille du viewport. Les container queries CSS répondent à la taille du conteneur d’un composant—un changement fondamental dans notre façon de construire des layouts responsives.
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
Cela importe car les composants vivent dans différents contextes. Une carte dans une barre latérale se comporte différemment de la même carte dans une zone de contenu principal. Les container queries permettent aux composants de s’adapter à leur espace réellement disponible, et non à la fenêtre du navigateur.
Avant les container queries, obtenir ce résultat nécessitait des resize observers JavaScript et une bascule manuelle de classes. Désormais, c’est du CSS déclaratif.
Animations Pilotées par le Défilement : Plus Besoin d’Intersection Observer
Les animations déclenchées par le défilement signifiaient traditionnellement importer des bibliothèques ou écrire du code Intersection Observer. Les animations CSS pilotées par le défilement remplacent les deux.
Deux types de timeline gèrent la plupart des cas d’usage :
Les scroll timelines lient la progression de l’animation à la position de défilement :
@keyframes grow {
from { width: 0; }
to { width: 100%; }
}
.progress-bar {
animation: grow linear;
animation-timeline: scroll();
}
Les view timelines se déclenchent lorsque les éléments entrent dans le viewport :
@keyframes fade-in {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.reveal {
animation: fade-in linear;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
Ces animations s’exécutent sur le thread du compositeur, offrant de meilleures performances que les alternatives JavaScript. Respectez toujours les préférences des utilisateurs avec @media (prefers-reduced-motion: reduce) pour désactiver ou simplifier les animations.
Discover how at OpenReplay.com.
L’API Popover : Infobulles et Menus Natifs
Construire des popovers accessibles nécessitait historiquement de gérer les pièges de focus, la détection des clics à l’extérieur, la gestion de la touche Échap et l’empilement des z-index. L’API Popover gère tout cela nativement.
<button popovertarget="menu">Ouvrir le Menu</button>
<div id="menu" popover>
<p>Contenu du menu ici</p>
</div>
Le navigateur automatiquement :
- Positionne le popover dans la couche supérieure (au-dessus de tout autre contenu)
- Le ferme lors d’un clic à l’extérieur ou d’une pression sur Échap
- Gère le focus de manière appropriée
- Prend en charge les annonces d’accessibilité
Stylisez les popovers avec CSS, y compris les animations d’entrée via @starting-style. La valeur par défaut popover="auto" se ferme lorsque les utilisateurs interagissent ailleurs, tandis que popover="manual" nécessite une fermeture explicite.
Accordéons Natifs avec <details name="">
L’élément <details> supporte les accordéons depuis des années. L’attribut name ajoute un comportement exclusif—un seul panneau ouvert à la fois :
<details name="faq">
<summary>Première question</summary>
<p>Contenu de la réponse</p>
</details>
<details name="faq">
<summary>Deuxième question</summary>
<p>Contenu de la réponse</p>
</details>
Pas de JavaScript. Accessibilité clavier complète. Support des lecteurs d’écran intégré. Stylisez l’état [open] et le pseudo-élément ::marker pour correspondre à votre design system.
L’Amélioration Progressive Reste Importante
Ces fonctionnalités bénéficient d’un large support, mais l’amélioration progressive reste une bonne pratique. Utilisez @supports pour fournir des solutions de repli :
@supports not (container-type: inline-size) {
/* Styles de repli utilisant les media queries */
}
Cette approche garantit une fonctionnalité de base partout tout en offrant des expériences améliorées là où c’est supporté.
Conclusion
Le CSS moderne sans JavaScript ne consiste pas à éviter complètement JavaScript—il s’agit de choisir le bon outil. Les solutions CSS déclaratives sont plus rapides à implémenter, plus faciles à maintenir et souvent plus performantes que leurs équivalents scriptés.
Commencez par auditer votre JavaScript actuel. S’il bascule des classes en fonction de l’état, positionne des infobulles ou surveille la position de défilement, CSS le gère probablement maintenant. Le navigateur fait le gros du travail. Laissez-le faire.
FAQ
Les fonctionnalités couvertes ici—:has(), container queries, animations pilotées par le défilement et l'API Popover—sont supportées par tous les navigateurs majeurs incluant Chrome, Firefox, Safari et Edge depuis 2025. Les animations pilotées par le défilement ont le support le plus restreint, donc vérifiez toujours caniuse.com pour les données de compatibilité actuelles et utilisez @supports pour les solutions de repli.
Le sélecteur :has() gère de nombreux scénarios de styling basés sur l'état mais a des limites. Il fonctionne bien pour le styling basé sur les états de formulaires, la présence d'enfants ou les conditions de fratrie. Pour une logique multi-étapes complexe, le rendu conditionnel ou la récupération de données, JavaScript reste nécessaire. Utilisez :has() pour les changements d'état visuels, pas pour la logique applicative.
Les animations CSS pilotées par le défilement surpassent généralement les alternatives JavaScript car elles s'exécutent sur le thread du compositeur, séparé du thread principal. Cela empêche le layout thrashing et les saccades. Cependant, animer des propriétés qui déclenchent des recalculs de layout comme width ou height peut toujours causer des problèmes de performance. Privilégiez transform et opacity pour de meilleurs résultats.
Utilisez la règle @supports pour détecter la disponibilité des fonctionnalités et fournir des styles alternatifs. Par exemple, @supports not (container-type: inline-size) vous permet de définir des solutions de repli avec media queries. Pour les solutions de repli dépendantes de JavaScript, vérifiez le support des fonctionnalités dans vos scripts avant d'initialiser des polyfills ou des implémentations alternatives.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.