Skip to content

Commit 3ae6658

Browse files
committed
[css-values-5] Add explainer for tree counting functions
Currently for sibling-count() and sibling-index()
1 parent d9282e9 commit 3ae6658

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Explainer: Tree counting functions - sibling-index() and sibling-count()
2+
3+
## Authors
4+
5+
- Rune Lillesveen ([@lilles](https://github.com/lilles)), Google
6+
7+
## Participate
8+
9+
- https://github.com/w3c/csswg-drafts/issues with prefix `[css-values-5]`
10+
11+
## The Problem
12+
13+
Authors have been asking for a convenient way of styling elements based on
14+
their DOM position among their siblings as well as the total number of siblings.
15+
16+
Example use cases for this are staggered animations setting the [animation- or
17+
transition-delay](https://chriscoyier.net/2023/11/29/element-indexes/) based on
18+
the sibling position, and [building a radial menu](https://una.im/radial-menu/).
19+
20+
It is possible to do this today through custom properties and exhaustingly
21+
listing all possible number of sibling through `:nth-child()` and
22+
`:has(:nth-child())` rules for sibling index and sibling count respectively.
23+
This trick is described on [css-tricks.com](https://css-tricks.com/how-to-wait-for-the-sibling-count-and-sibling-index-functions/#aa-rubbing-two-sticks-together)
24+
25+
## The Solution
26+
27+
The CSS Values and Units Module Level 5 introduces [tree counting functions](https://drafts.csswg.org/css-values-5/#tree-counting),
28+
specifically `sibling-index()` and `sibling-count()`. These functions can be
29+
used as `<integer>` values directly or combined with other values in `calc()`
30+
expressions. The `sibling-index()` and `sibling-count()` functions evaluate to
31+
integers at computed value time based on the flat tree position of the element.
32+
33+
## Demo
34+
35+
Here is a demo that combines using `sibling-index()` and `sibling-count()` for
36+
both transform and staggered transitions. The items are distributed in a half-
37+
circle, the half-circle radius adapts to the number of elements, and the fan-
38+
out transition that spreads the elements is delayed for each element based on
39+
its sibling position.
40+
41+
```html
42+
<!DOCTYPE html>
43+
<style>
44+
body { margin: 0; }
45+
:root { height: 100vh; }
46+
.item {
47+
width: 50px;
48+
height: 50px;
49+
background: teal;
50+
position: absolute;
51+
inset: 0;
52+
bottom: 20px;
53+
place-self: center;
54+
border-radius: 50%;
55+
transition: transform ease-out 0.5s;
56+
transition-delay: calc(sibling-index() * 50ms);
57+
--angle: calc(180.0deg * ((sibling-index() - 1) / (sibling-count() - 1)));
58+
transform: rotate(var(--angle)) translate(0);
59+
}
60+
:root:hover .item {
61+
transform: rotate(var(--angle)) translate(calc(-20px * sibling-count()));
62+
}
63+
</style>
64+
<div class="item"></div>
65+
<div class="item"></div>
66+
<div class="item"></div>
67+
<div class="item"></div>
68+
<div class="item"></div>
69+
<div class="item"></div>
70+
<div class="item"></div>
71+
<div class="item"></div>
72+
```
73+
74+
## Resources
75+
76+
- [CSS Values 5 Specification](https://drafts.csswg.org/css-values-5/#tree-counting)
77+
- [How to Wait for the sibling-count() and sibling-index() Functions](https://css-tricks.com/how-to-wait-for-the-sibling-count-and-sibling-index-functions/)
78+
- [Element Indexes](https://chriscoyier.net/2023/11/29/element-indexes/)
79+
- [Possible Future CSS: Tree-Counting Functions and Random Values](https://kizu.dev/tree-counting-and-random/)
80+
- [Building a no-JS radial menu with CSS trigonometry, popover, and anchor positioning](https://una.im/radial-menu/)

0 commit comments

Comments
 (0)