Skip to content

[css-lists] Algorithm for initial counter value in reversed list should repeat the last increment instead of the 1st one  #6797

Open
@Loirooriol

Description

@Loirooriol

https://drafts.csswg.org/css-lists/#instantiating-counters

  1. Let num be 0.
  2. Let first be true.
  3. For each element or pseudo-element el that increments or sets the same counter in the same scope:
    1. Let incrementNegated be el’s counter-increment integer value for this counter, multiplied by -1.
    2. If first is true, then add incrementNegated to num and set first to false.
    3. If el sets this counter with counter-set, then add that integer value to num and break this loop.
    4. Add incrementNegated to num.
  4. 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:

  1. Let num be 0.
  2. Let incrementNegated be 0.
  3. For each element or pseudo-element el that increments or sets the same counter in the same scope:
    1. Set incrementNegated to el’s counter-increment integer value for this counter, multiplied by -1.
    2. If el sets this counter with counter-set, then add that integer value to num and break this loop.
    3. Add incrementNegated to num.
  4. Add incrementNegated to num.
  5. Return num.

Or, taking #6738 into account, repeat the last non-zero increment:

  1. Let num be 0.
  2. Let lastNonZeroIncrementNegated be 0.
  3. For each element or pseudo-element el that increments or sets the same counter in the same scope:
    1. Let incrementNegated to el’s counter-increment integer value for this counter, multiplied by -1.
    2. If incrementNegated is not zero, set lastNonZeroIncrementNegated to incrementNegated.
    3. If el sets this counter with counter-set, then add that integer value to num and break this loop.
    4. Add incrementNegated to num.
  4. Add lastNonZeroIncrementNegated to num.
  5. 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>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions