Skip to content

[css-values] Function to retrieve index of element among siblings, or counter on element as integer #1869

Closed

Description

@Nokel81

Currently you can write the following with the :nth-child or similar style selectors

.foobar>*:nth-child(2n) {
    background-color: lime;
}

Which means that every second child has a background colour of lime. However you cannot do something like the following:

.foobar {
    display: grid;
    grid-template-columns: 100px 1fr;
}
.foobar>*:nth-child(2n) {
    grid-column: 1/2;
    grid-row: n;
}
.foobar>*:nth-child(2n+1) {
    grid-column: 2/3;
    grid-row: n;
}

I think that this would be very useful and would make working with grids quite a bit more easy

Activity

  1. tabatkins commented on Oct 13, 2017

    @tabatkins
    Member

    What would happen in:

    .foo > :nth-child(n) > :nth-child(2n) { grid-row: n; }
    

    ?

  2. Nokel81 commented on Oct 13, 2017

    @Nokel81
    Author

    The second one would overwrite the first value. A way around this would be to allow other letters besides n

  3. Loirooriol commented on Oct 14, 2017

    @Loirooriol
    Contributor

    I think allowing counter() to return an integer would be a better way to address this kind of problems.

    .foobar {
      counter-reset: n;
    }
    .foobar > * {
      counter-increment: n;
      grid-row: counter(n integer);
    }
  4. Nokel81 commented on Oct 14, 2017

    @Nokel81
    Author

    Having not known of counters before this, that is cool. Now, yes I believe that that is a much better way of addressing this problem

  5. tabatkins commented on Oct 27, 2017

    @tabatkins
    Member

    An integer-returning counter() is definitely one way to address this. We could possibly also go with a more direct sibling-index() function that just returns your index in among your siblings, so you don't have to set up a counter explicitly. I can definitely see some uses for this.

    If you want the index of an ancestor element to use in a further descendent, you just need to (a) register a custom property to have a <number> type, and (b) set the property using sibling-index() on that parent element. Then you can use var() on the descendant to fetch the value. (You need to register the prop to get CSS to evaluate the function at the place you originally used it; an unregistered var will just preserve the function itself and resolve it on the descendant instead.)

  6. changed the title [-][css-selectors] nth-child produces a local variable[/-] [+][css-values] Function to retrieve index of element among siblings, or counter on element[/+] on Oct 27, 2017
  7. changed the title [-][css-values] Function to retrieve index of element among siblings, or counter on element[/-] [+][css-values] Function to retrieve index of element among siblings, or counter on element as integer[/+] on Oct 27, 2017
  8. Loirooriol commented on Oct 27, 2017

    @Loirooriol
    Contributor

    If a specific sibling-index() function is added, I guess it could also accept an argument to be consistent with the of S syntax of :nth-child(). For example, sibling-index(S) would return the (1-based) index of the current element among its inclusive siblings that match the selector list S. The problem is if the element does not match S, then maybe return 0.

  9. Nokel81 commented on Oct 28, 2017

    @Nokel81
    Author

    The idea of a selector as well is cool but another way to get the parent's sibling count would be sibling-index(1p) for the first parent

  10. jakearchibald commented on Nov 3, 2019

    @jakearchibald
    Contributor

    This, along with a way to get the number of children in an element, would be really nice for staggered animations.

    .parent {
      --parent-children-count: children-count();
    }
    .parent .anim {
      /* Stagger from start to end */
      animation-delay: calc(sibling-index() * 100ms);
      /* Stagger from end to start */
      animation-delay: calc((var(--parent-children-count) - sibling-index()) * 100ms);
    }

    (@Nokel81 maybe the above shows that you don't need a special way to get values from the parent)

  11. shshaw commented on Dec 4, 2019

    @shshaw

    My entire Splitting.js library is based around giving these values as CSS variables. I would love for my library to become obsolete (though that would also require ::nth-letter as well 😄).

    animation-delay and transition-delay are the most commonly used, but it also allows for other amazing effects. Here's a large collection of uses people have found for these values in CSS: https://codepen.io/collection/XpROaV/

    My thoughts on the syntax would be:

    • child-count() returns the number of child elements
      (akin to ['A','B','C'].length)

    • sibling-index() returns the element's index in relation to its siblings
      (akin to ['A','B','C'].indexOf('B'))

    • sibling-count() returns the total count of adjacent elements
      (the parent's child-count() - 1 )

    Using sibling-count() you can then calculate a 0-1 range of the element's "position" in the parent. For example:

    .children {
      animation: fade-in 1s linear;
      /* Stagger in all children over the course of 1s */
      animation-delay: calc( 1s * ( sibling-index() / sibling-count() ) );
    }
    

    Demo using CSS variables

    You can also calculate "distance" from the end (as @jakearchibald showed), or even calculate from the center (example using CSS Variables]

  12. jakearchibald commented on Jul 20, 2023

    @jakearchibald
    Contributor

    It seems like the newer issue, #4559, has more traction. Maybe this should close?

  13. tabatkins commented on Jul 22, 2023

    @tabatkins
    Member

    Yeah, since #4559 is the version that actually got a WG resolution, I'll close this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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