Description
https://drafts.csswg.org/css-lists/#instantiating-counters
- Let num be 0.
- Let first be true.
- For each element or pseudo-element el that increments or sets the same counter in the same scope:
- Let incrementNegated be el’s
counter-increment
integer value for this counter, multiplied by -1.- If first is true, then add incrementNegated to num and set first to false.
- If el sets this counter with
counter-set
, then add that integer value to num and break this loop.- Add incrementNegated to num.
- Return num.
Problem 1: the value of the last item is the increment of the 1st one.
Let's consider this basic list:
<ol reversed><!-- 5 -->
<li style="counter-increment: list-item -1"><!-- 4 --></li>
<li style="counter-increment: list-item -1"><!-- 3 --></li>
<li style="counter-increment: list-item -1"><!-- 2 --></li>
<li style="counter-increment: list-item -1"><!-- 1 --></li>
</ol>
The initial value is 5 which is the sum of the counter-increments, with the 1st one counted twice. The result looks good.
Then, let's change one increment in the middle:
<ol reversed><!-- 6 -->
<li style="counter-increment: list-item -1"><!-- 5 --></li>
<li style="counter-increment: list-item -1"><!-- 4 --></li>
<li style="counter-increment: list-item -2"><!-- 2 --></li>
<li style="counter-increment: list-item -1"><!-- 1 --></li>
</ol>
Only the preceding elements are affected, as expected. But now let's undo and change the first increment instead:
<ol reversed><!-- 7 -->
<li style="counter-increment: list-item -2"><!-- 5 --></li>
<li style="counter-increment: list-item -1"><!-- 4 --></li>
<li style="counter-increment: list-item -1"><!-- 3 --></li>
<li style="counter-increment: list-item -1"><!-- 2 --></li>
</ol>
Now all the values changed! That's because, by counting the 1st increment twice, the value of the last item will precisely be the increment of the 1st item (assuming there is no counter-set
). This doesn't seem to make much sense.
Problem 2: counter-set
to the current value affects preceding values
Let's consider, again,
<ol reversed><!-- 6 -->
<li style="counter-increment: list-item -1"><!-- 5 --></li>
<li style="counter-increment: list-item -1"><!-- 4 --></li>
<li style="counter-increment: list-item -2"><!-- 2 --></li>
<li style="counter-increment: list-item -1"><!-- 1 --></li>
</ol>
and then add a counter-set: list-item 2
to the item that already had value 2:
<ol reversed><!-- 5 -->
<li style="counter-increment: list-item -1"><!-- 4 --></li>
<li style="counter-increment: list-item -1"><!-- 3 --></li>
<li style="counter-increment: list-item -2; counter-set: list-item 2"><!-- 2 --></li>
<li style="counter-increment: list-item -1"><!-- 1 --></li>
</ol>
Seems unexpected that when setting the counter to the same value that it would have without counter-set
, the values of the preceding items change. Basically, instead of using the counter-increment
of the 3rd item as the difference between the 2nd and 3rd items, it's using the counter-increment of the 1st item!
Solution: use the last increment twice, instead of the 1st one
The algorithm should probably be more like:
- Let
num
be 0. - Let
incrementNegated
be 0. - For each element or pseudo-element
el
that increments or sets the same counter in the same scope:- Set
incrementNegated
toel
’scounter-increment
integer value for this counter, multiplied by -1. - If
el
sets this counter withcounter-set
, then add that integer value tonum
and break this loop. - Add
incrementNegated
tonum
.
- Set
- Add
incrementNegated
tonum
. - Return
num
.
Or, taking #6738 into account, repeat the last non-zero increment:
- Let
num
be 0. - Let
lastNonZeroIncrementNegated
be 0. - For each element or pseudo-element
el
that increments or sets the same counter in the same scope:- Let
incrementNegated
toel
’scounter-increment
integer value for this counter, multiplied by -1. - If
incrementNegated
is not zero, setlastNonZeroIncrementNegated
toincrementNegated
. - If
el
sets this counter withcounter-set
, then add that integer value tonum
and break this loop. - Add
incrementNegated
tonum
.
- Let
- Add
lastNonZeroIncrementNegated
tonum
. - Return
num
.
Then we would have:
<ol reversed><!-- 6 -->
<li style="counter-increment: list-item -2"><!-- 4 --></li>
<li style="counter-increment: list-item -1"><!-- 3 --></li>
<li style="counter-increment: list-item -1"><!-- 2 --></li>
<li style="counter-increment: list-item -1"><!-- 1 --></li>
</ol>
<ol reversed><!-- 6 -->
<li style="counter-increment: list-item -1"><!-- 5 --></li>
<li style="counter-increment: list-item -1"><!-- 4 --></li>
<li style="counter-increment: list-item -2; counter-set: list-item 2"><!-- 2 --></li>
<li style="counter-increment: list-item -1"><!-- 1 --></li>
</ol>