/ Articles
Utiliser if dans du... CSS 😱
Le CSS n'en finit plus de se transformer et d'incorporer toujours plus de nouvelles fonctionnalités qui requéraient auparavant de passer par des pré-processeurs type Sass ou Less.
C'est encore le cas avec l'arrivée de la très attendue (et inespérée !) fonction if() qui permet d'exprimer directement dans notre feuille de style une logique conditionnelle sans passer par les divers moyens détournés que sont les media ou container queries, les sélecteurs d'attributs ou les fonctions css calc() et clamp().
Prenons un cas d'usage assez banal — styliser un élément en fonction de la valeur d'un de ses attributs — avec ces badges reflétant un statut :
Chaque badge porte un attribut data-status. On souhaite alors différencier la couleur de chaque badge en fonction de la valeur passée à data-status (pending, success, error, etc.).
Sans if()
Plusieurs solutions sont possibles. Persnonellement, j'ai l'habitude de créer des variables CSS pour contrôler les propriétés qui m'intéressent et d'en modifier ensuite les valeurs dans chaque sous-sélecteur de type [data-status="XXX"].
.badge {
--color: #0ea5e9; /* default fallback color */
--background-color: #cffafe; /* default fallback background color */
border: 1px solid var(--color);
background-color: var(--background-color);
color: var(--color);
/* ... */
}.badge[data-status="pending"] {
--color: #9333ea;
--border-color: #f5f3ff;
}.badge[data-status="success"] {
--color: #16a34a;
--background-color: #dcfce7;
}.badge[data-status="error"] {
--color: #ef4444;
--background-color: #fee2e2;
}L'inconvénient de cette approche est que la forme conditionnelle n'est pas forcément explicite et nécessite plusieurs sélecteurs CSS pour cibler tous les états possibles du badge.
Avec if()
Grâce à cette nouvelle fonction if(), on peut définir tous ces changements dans le même sélecteur.
On commence par définir une variable CSS custom --status qui récupère automatiquement la valeur de l'attribut [data-status] porté par l'élément :
.badge {
--status: attr(data-status type(<custom-indent>));
/* ... */
}Puis sur la propriété css visée on appelle la fonction if() pour en faire varier la valeur suivant celle de --status :
.badge {
--status: attr(data-status type(<custom-indent>));
color: if(
style(--status: pending): #9333ea;
style(--status: success): #16a34a;
style(--status: error): #ef4444;
else: #0ea5e9
);
/* Même logique pour la propriété background-color */
}Il eût été plus intuitif d'avoir à écrire --status == pending pour comparer les deux valeurs mais la bonne syntaxe est bien style(--status: pending).
Quelle que soit la condition testée, la syntaxe générale du if() en css restera la même :
property : if(condition1: value; condition2: value; ... else: value);
Au final, c'est un poil moins verbeux 🤏 et surtout bien plus clair dans l'intention.
Compatibilité avec les navigateurs
Comme souvent, c'est Chrome qui a pris les devants en termes de support en embarquant le if() dès la version 137 (sortie fin mai 2025). La plupart des autres navigateurs non basés sur Chromium sont encore aux fraises sur le sujet, la prudence est donc de mise avant d'envoyer ça en production.
Est-ce une si bonne idée ?
Plutôt, dans la mesure où on peut régler de façon bien plus élégante et maintenable certains problèmes de layout et de style. L'exemple proposé par Una Kravets pour classer des tickets dans différentes colonnes est particulièrement ingénieux et permet bien de sentir l'intérêt de cette nouvelle fonctionnalité 👇
Le revers de la médaille cependant avec ces syntaxes plus "programmatiques" qui émergent c'est qu'elles tendent à éloigner le CSS de sa nature très déclarative et à le rapprocher d'un langage de programmation avec un coût d'entrée et de maîtrise de plus en plus élevé.
Or c'est précisément cet aspect déclaratif commun à HTML et CSS qui permet de limiter la casse lorsqu'on envoyait du CSS trop récent dans des navigateurs avec des versions anciennes puisqu'il suffit à l'interpréteur de zapper les propriétés ou valeurs inconnues — là où un compilateur Javascript crashe méchamment s'il croise une syntaxe inconnue postérieur à sa version maximum supportée.
À voir donc si ce surplus de logique dans le CSS ne va pas aggraver les problèmes de rétrocompatibilité et compliquer le débuggage puisque l'interprétation en deviendra plus délicate — même si des outils comme PostCSS permettent généralement de mitiger cette difficulté en transpilant le CSS moderne pour le rendre compatible avec les anciennes versions de navigateurs.