Раньше, чтобы применить уникальные стили к каждому элементу списка, требовались сложные циклы :nth-child или JavaScript для вставки встроенных стилей. Современный CSS предоставляет sibling-index() и sibling-count() для выполнения этих вычислений непосредственно в таблице стилей, что позволяет создавать динамические макеты и цветовые системы, которые автоматически адаптируются при добавлении или удалении элементов.
Динамические цветовые системы
Вы можете создать цветовой спектр для группы дочерних элементов, рассчитав уникальное значение оттенка или яркости для каждого из них. Это обеспечивает стабильный эффект градиента независимо от количества элементов.
.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%
);
}
Симметричный макет и эффекты веера
Чтобы создать симметричные эффекты (например, "веер" или центрирование элементов), используйте общее количество, чтобы найти среднюю точку списка.
.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))));
}
Круговое и сложное позиционирование
Объединив эти функции с тригонометрическими функциями CSS (sin(), cos()), вы можете разместить элементы по идеальному кругу без ручного указания координат.
.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))
);
}
Резервные стратегии
Если sibling-index() и sibling-count() не поддерживаются, добавьте резервный вариант, внедрив пользовательские свойства CSS с помощью JavaScript. ОБЯЗАТЕЛЬНО. Используйте обнаружение функций с помощью CSS.supports(), чтобы скрипт запускался только при необходимости.
/* 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);
});
}
В CSS используйте эти переменные как базовые и переопределяйте их с помощью нативных функций в блоке @supports. ОБЯЗАТЕЛЬНО. Вы ДОЛЖНЫ заключить переопределения нативных функций в @supports, чтобы переменные оставались действительными в старых браузерах.
.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();
}
}