Auparavant, pour appliquer des styles uniques à chaque élément frère d'une liste, il fallait utiliser des boucles :nth-child complexes ou du code JavaScript pour injecter des styles intégrés. Le CSS moderne fournit sibling-index() et sibling-count() pour effectuer ces calculs directement dans votre feuille de style, ce qui permet d'obtenir des mises en page et des systèmes de couleurs dynamiques qui s'adaptent automatiquement à l'ajout ou à la suppression d'éléments.
Systèmes de couleurs dynamiques
Vous pouvez créer un spectre de couleurs sur un groupe d'éléments frères en calculant une valeur de teinte ou de luminosité unique pour chaque enfant. Cela garantit un effet de dégradé cohérent, quel que soit le nombre d'éléments.
.swatch {
/* Calculate hue by dividing the full 360deg circle by total siblings */
/* and multiplying by the current element's 1-based index */
background-color: hsl(
calc(360deg / sibling-count() * sibling-index()),
70%,
50%
);
}
Mise en page symétrique et effets de ventilateur
Pour créer des effets symétriques (comme un "éventail" ou des éléments centrés), utilisez le nombre total pour trouver le milieu de la liste.
.card {
/* Find the center index (e.g., 3 if there are 5 siblings) */
--center: calc((sibling-count() + 1) / 2);
/* Rotate items away from the center: negative for left, positive for right */
/* center element gets 0deg rotation */
transform: rotate(calc(10deg * (sibling-index() - var(--center))));
}
Positionnement circulaire et complexe
En combinant ces fonctions avec la trigonométrie CSS (sin(), cos()), vous pouvez placer des éléments dans un cercle parfait sans aucune coordonnée manuelle.
.orb {
/* Calculate the angle for this item's position on a 360deg circle */
--angle: calc(360deg / sibling-count() * sibling-index());
--radius: 150px;
/* Set the pre-transformed position for all items to be centered */
position: absolute;
place-self: center;
/* Position each element around the parent center */
transform: translate(
calc(cos(var(--angle)) * var(--radius)),
calc(sin(var(--angle)) * var(--radius))
);
}
Stratégies de remplacement
Si sibling-index() et sibling-count() ne sont pas compatibles, fournissez une solution de remplacement en injectant des propriétés CSS personnalisées via JavaScript. OBLIGATOIRE : Utilisez la détection de fonctionnalités avec CSS.supports() pour vous assurer que le script ne s'exécute que lorsque cela est nécessaire.
/* MANDATORY: Check for native support before applying fallback */
if (!CSS.supports('top: calc(sibling-index() * 1px)')) {
const items = document.querySelectorAll('.item');
items.forEach((item, index) => {
/* MANDATORY: Injected index must be 1-based to match native function */
item.style.setProperty('--sibling-index', index + 1);
item.style.setProperty('--sibling-count', items.length);
});
}
Dans votre CSS, utilisez ces variables comme base et remplacez-les par des fonctions natives dans un bloc @supports. OBLIGATOIRE : vous DEVEZ encapsuler les remplacements de fonctions natives dans @supports pour vous assurer que les variables restent valides dans les anciens navigateurs.
.item {
/* 1. Set base values using variables (from JS fallback) */
--index: var(--sibling-index);
--count: var(--sibling-count);
/* 2. Use the computed variables - replace this with your implementation-specific styles */
background-color: hsl(calc(360deg / var(--count) * var(--index)), 70%, 50%);
}
@supports (top: calc(sibling-index() * 1px)) {
.item {
/* 3. Override with native functions ONLY if supported */
--index: sibling-index();
--count: sibling-count();
}
}