Joshua Muheim
Joshua Muheim

Reputation: 13243

CSS counter with nested elements (counter value seems to increment for child elements, too)

I want to define a CSS counter that increments by 1 for each [data-fragment-index] element (inside a <section class="slide">):

section.slide [data-fragment-index] {
  counter-increment: my-counter;
}

This is the result:

screenshot

Instead of getting 1, 2, 3, 4, and 5, I get 1, 3, 3, 4, and 5.

What's happening? I guess it has something to do with the nested elements, but I don't see the solution.

Here's a Codepen demonstrating the issue: https://codepen.io/jmuheim/pen/WbNQEGm?editors=1100

section.slide [data-fragment-index] {
  counter-increment: my-counter;
}

.fragment {
  position: relative;
}

.fragment::after {
  position: absolute;
  top: 3px;
  right: 5px;
  content: counter(my-counter);
  background-color: #f28b48;
  border-radius: 50%;
  border: 2px solid #fff;
  width: 16px;
  font-weight: bold;
  height: 16px;
  text-align: center;
  color: #fff;
}
<section class="slide">
  <p class="fragment" data-fragment-index="0">A paragraph</p>
  <ul>
    <li class="fragment" data-fragment-index="0">A list item

      <ul>
        <li class="fragment" data-fragment-index="1">A nested list item</li>
      </ul>
    </li>
    <li class="fragment" data-fragment-index="2">Another list item
  </ul>
  <p class="fragment">Last paragraph</p>
</section>

Upvotes: 0

Views: 39

Answers (1)

A Haworth
A Haworth

Reputation: 36605

Remember that an after pseudo element comes after all its child elements, so the value of the counter that is put out then is what it is at the end of that element.

Try putting another child li element in there and you will see the counter goes to 4 and so on.

This snippet instead uses the before pseudo element and in this case the counting is as you want it - the counter has not been incremented by all the children yet.

.fragment {
  counter-increment: my-counter;
}

.fragment {
  position: relative;
}

.fragment::before {
  position: absolute;
  top: 3px;
  right: 150px;
  content: counter(my-counter);
  background-color: #f28b48;
  border-radius: 50%;
  border: 2px solid #fff;
  width: 16px;
  font-weight: bold;
  height: 16px;
  text-align: center;
  color: #fff;
}
<section class="slide">
  <p class="fragment" data-fragment-index="0">A paragraph</p>
  <ul>
    <li class="fragment" data-fragment-index="0">A list item

      <ul>
        <li class="fragment" data-fragment-index="1">A nested list item</li>
      </ul>
    </li>
    <li class="fragment" data-fragment-index="2">Another list item
  </ul>
  <p class="fragment">Last paragraph</p>
</section>

Upvotes: 0

Related Questions