Le CSS continue d’évoluer avec des fonctionnalités de plus en plus puissantes. Parmi elles, @property en CSS permet de déclarer des propriétés personnalisées exploitables dans les animations et transitions. Associé à position-anchor
et :has()
, cet outil offre des effets dynamiques sans JavaScript.
Dans cet article, nous allons analyser un exemple concret qui exploite @property en CSS pour créer une interaction fluide avec des boutons radio.
Boutons radio rebondissants utilisant un CSS moderne

@property --_x {
syntax: "<number>";
inherits: false;
initial-value: 0;
}
.container {
--s: 1em; /* control the size */
--c: #009688; /* the active color */
display: grid;
position: relative;
}
.container:before {
content: "";
position: absolute;
position-anchor: --checkbox;
height: calc(var(--s)/2);
aspect-ratio: 1;
--_y: clamp(-1,var(--_x)*9999,1); /* until better support for sign() */
left: max(-80px,var(--s)/4 - var(--_x)*var(--_y)*1px);
top: calc(anchor(top) + var(--s)/4);
background: var(--c);
border-radius: 50%;
transition: top .4s linear,--_x cubic-bezier(.1,3000,.7,3000) .4s;
}
input {
height: var(--s);
aspect-ratio: 1;
border: calc(var(--s)/8) solid #939393;
border-radius: 50%;
outline-offset: calc(var(--s)/10);
appearance: none;
transition: .3s .1s;
}
input:checked {
border-color: var(--c);
anchor-name: --checkbox;
}
/* The hacky part ... */
.container:has(label:nth-child(1) input:checked):before {--_x:.01}
.container:has(label:nth-child(2) input:checked):before {--_x:.02}
.container:has(label:nth-child(3) input:checked):before {--_x:.03}
/* .container:has(label:nth-child(N) input:checked):before {--_x:.0N}*/
🧐 Qu’est-ce que @property en CSS ?
1️⃣ Définition et utilité
@property --_x {
syntax: "<number>";
inherits: false;
initial-value: 0;
}
La directive @property
permet d’introduire des propriétés CSS personnalisées compatibles avec les animations et transitions. Contrairement aux variables CSS classiques (--my-var
), ces propriétés peuvent être animées.
📌 Pourquoi utiliser @property en CSS ?
✅ Contrôle avancé sur les animations
✅ Optimisation des performances
✅ Évite d’avoir recours à JavaScript
👉 Ici, --_x
servira à contrôler la position dynamique de notre élément animé.
2️⃣ Création du conteneur interactif
.container {
--s: 1em; /* Contrôle la taille */
--c: #009688; /* Couleur active */
display: grid;
position: relative;
}
Le conteneur utilise des variables CSS dynamiques pour la taille (--s
) et la couleur (--c
). Il fonctionne comme un espace interactif où notre animation va se produire.
3️⃣ Animer un élément avec @property en CSS
.container:before {
content: "";
position: absolute;
position-anchor: --checkbox;
height: calc(var(--s)/2);
aspect-ratio: 1;
--_y: clamp(-1,var(--_x)*9999,1);
left: max(-80px,var(--s)/4 - var(--_x)*var(--_y)*1px);
top: calc(anchor(top) + var(--s)/4);
background: var(--c);
border-radius: 50%;
transition: top .4s linear, --_x cubic-bezier(.1,3000,.7,3000) .4s;
}
🟢 Ce qu’il se passe ici :
🔹 position-anchor: --checkbox
: Ancre l’élément en fonction du bouton sélectionné.
🔹 --_x
et clamp()
: Ajuste dynamiquement la position de l’élément.
🔹 transition
avec cubic-bezier()
: Applique un effet d’animation progressif et naturel.
4️⃣ Interaction avec des inputs radio
input {
height: var(--s);
aspect-ratio: 1;
border: calc(var(--s)/8) solid #939393;
border-radius: 50%;
outline-offset: calc(var(--s)/10);
appearance: none;
transition: .3s .1s;
}
input:checked {
border-color: var(--c);
anchor-name: --checkbox;
}
✅ Explications :
- Les boutons radio sont personnalisés avec un
aspect-ratio: 1
pour les rendre circulaires. - Lorsqu’un
input
est coché, il change de couleur et devient une ancre (anchor-name: --checkbox
). - Supprime l’apparence par défaut avec
appearance: none
5️⃣ La magie du :has()
pour déclencher l’animation
.container:has(label:nth-child(1) input:checked):before {--_x:.01}
.container:has(label:nth-child(2) input:checked):before {--_x:.02}
.container:has(label:nth-child(3) input:checked):before {--_x:.03}
🔥 Utilisation astucieuse de :has()
- Détecte un
input:checked
sans JavaScript - Modifie dynamiquement
--_x
pour animer l’élément - Compatible avec tous les labels (
nth-child(N)
) pour gérer plusieurs options
🎬 Conclusion
L’utilisation de @property en CSS combinée à :has()
et position-anchor
ouvre de nouvelles possibilités en matière d’animation et d’interaction web, sans nécessiter JavaScript.
Avantages de cette approche :
✅ Aucune dépendance JavaScript
✅ Animation CSS performante
✅ Compatible avec des styles adaptatifs
💡 Possibilités d’amélioration ?
- Tester la compatibilité sur divers navigateurs (🚨
position-anchor
n’est pas encore largement supporté). - Ajouter des effets supplémentaires comme une échelle (
transform: scale()
). - Intégrer ce principe dans des UI interactives avancées.
🚀 Que pensez-vous de cette technique ? Avez-vous déjà expérimenté @property
dans vos projets ?