Skip to content

Latest commit

 

History

History
80 lines (65 loc) · 3.13 KB

tree-counting-explainer.md

File metadata and controls

80 lines (65 loc) · 3.13 KB

Explainer: Tree counting functions - sibling-index() and sibling-count()

Authors

  • Rune Lillesveen (@lilles), Google

Participate

The Problem

Authors have been asking for a convenient way of styling elements based on their DOM position among their siblings as well as the total number of siblings.

Example use cases for this are staggered animations setting the animation- or transition-delay based on the sibling position, and building a radial menu.

It is possible to do this today through custom properties and exhaustingly listing all possible number of sibling through :nth-child() and :has(:nth-child()) rules for sibling index and sibling count respectively. This trick is described on css-tricks.com

The Solution

The CSS Values and Units Module Level 5 introduces tree counting functions, specifically sibling-index() and sibling-count(). These functions can be used as <integer> values directly or combined with other values in calc() expressions. The sibling-index() and sibling-count() functions evaluate to integers at computed value time based on the flat tree position of the element.

Demo

Here is a demo that combines using sibling-index() and sibling-count() for both transform and staggered transitions. The items are distributed in a half- circle, the half-circle radius adapts to the number of elements, and the fan- out transition that spreads the elements is delayed for each element based on its sibling position.

<!DOCTYPE html>
<style>
  body { margin: 0; }
  :root { height: 100vh; }
  .item {
    width: 50px;
    height: 50px;
    background: teal;
    position: absolute;
    inset: 0;
    bottom: 20px;
    place-self: center;
    border-radius: 50%;
    transition: transform ease-out 0.5s;
    transition-delay: calc(sibling-index() * 50ms);
    --angle: calc(180.0deg * ((sibling-index() - 1) / (sibling-count() - 1)));
    transform: rotate(var(--angle)) translate(0);
  }
  :root:hover .item {
    transform: rotate(var(--angle)) translate(calc(-20px * sibling-count()));
  }
</style>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>

Resources