Skip to content

[css-values] Proposal: add sibling-count() and sibling-index() #4559

Closed
@argyleink

Description

@argyleink

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

splitting


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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions