Description
Problem
Currently we can query a child based on it's child index position or query on children length (with some complex syntax), but we can't use the index or length as values in our styles. Feels like they're known, but not accessible.
so we end up doing stuff like this:
.el {
--delay: calc(var(--i, 1) * 400ms);
animation: fadeIn 1000ms var(--delay) forwards;
width: 100px;
height: 100px;
background: darkorchid;
margin: 20px;
opacity: 0;
}
.el:nth-child(2) {
--i: 2;
}
.el:nth-child(3) {
--i: 3;
}
@keyframes fadeIn {
100% { opacity: 1; }
}
above source from Codepen
Proposal
2 new functions: sibling-count()
and sibling-index()
. These should report values based on element count, not node count.
sibling-count()
This function returns the total length of sibling elements as a number, similar to node.childElementCount
(docs) or node.children.length
but accessible from a sibling. Consider this like a child asking "how many siblings they have".
example usage
Dynamic background color that changes based on total children in the list
ul > li {
background-color: hsl(sibling-count() 50% 50%);
}
sibling-index()
This function returns the contextual child index as a number. Similar to the value queried with nth-child
, this would be a get() call for the contextual child's index in the tree. Consider this like a child asking "what position am I in this family".
example usage
Dynamic background color that changes based on child index position, resulting in a stepped gradient effect
ul > li {
background-color: hsl(calc(sibling-index() * 10) 50% 50%);
}
All Together
Example code is a slightly modified version of Jake Archibald's comment here 👍
ul > li {
/* Stagger from start to end */
animation-delay: calc(sibling-index() * 100ms);
/* Stagger from end to start */
animation-delay: calc(sibling-count() - sibling-index() * 100ms);
}
Use Cases
- staggered animations: example1 example2
- dynamic & contextual color systems
- dynamic & contextual spacing
- dynamic & contextual distance
- etc
Conclusion
Most other proposals for similar functionality, request access to counters()
as a unit that can be passed to calc()
. But I feel that is overloading the counters feature and is rooted in a mindset of leveraging something "close" to what is needed, where what's actually wanted is the child index position for visually reasonable and meaningful UI feedback and presentation.
By proposing a solution that doesn't involve counters, I hope to bypass much of the pain points associated with the feature to help unblock the large and ever-growing set of use cases that could leverage these contextual values.
Sources & Chatter
#1869
#1176
#1026
https://www.w3.org/TR/selectors-4/#child-index
https://twitter.com/shshaw/status/1201978228375724032?s=20
https://twitter.com/smfr/status/1202276694230306816?s=20 @smfr