Search code examples
htmlcssfirefoxhtml-listscss-counter

Is Firefox violating spec by its odd cumulative application of counting to LI markers when there's a counter-reset declaration?


Usually when CSS counters are used on lists, the OL list-style-type is set to none and and ::before pseudo-elements are used instead of true list markers.

However, I noticed that in Firefox (69.0, target:x86_64-apple-darwin, running on MacOS Mojave) the presence of a counter-reset does something odd to actual list markers. Consider:

ol {counter-reset: some-counter;}
li::before {
  content: "Marker should be: " counter(some-counter) ".";
  counter-increment: some-counter;
}

ol.alpha {list-style-type:lower-alpha;}
ol.alpha > li::before{content: "Marker should be: " counter(some-counter, lower-alpha) ".";}
<h2>List A</h2>
<ol>
  <li>
    <ol>
      <li></li>
      <li></li>
      <li></li>
    </ol>
  </li>
  <li>
    <ol>
      <li></li>
      <li></li>
      <li></li>
    </ol>
  </li>
</ol>

<h2>List B</h2>
<ol>
  <li>
    <ol class="alpha">
      <li></li>
      <li></li>
      <li></li>
    </ol>
  </li>
  <li>
    <ol class="alpha">
      <li style="counter-reset: some-counter"></li>
      <li></li>
      <li></li>
    </ol>
  </li>
</ol>

Chrome and Safari render as expected, but in FF, List A gets rendered as:

FF result 1

and List B gets rendered as:

enter image description here

In other words, when going through a two-level list, FF is keeping track of:

  1. A shared list marker counter that is incremented both when it hits both the first-tier LIs and any LIs nested inside.
  2. A counter instance of "some-counter" that applies only to the outer list
  3. Counter instances of "some-counter" that apply only to any inner lists

FF's list markers display that shared counter (with any necessary translation, e.g to lower-alpha in List B above), while ::before pseudo-elements display the "some-counter" instances appropriate to their level.

If you comment out the counter-reset, FF goes back to expected behavior in its markers. (Even setting "counter-reset:none" still causes the strange behavior.)

Is this a bug, or is there some reason that there would be undefined behavior in list markers when a counter-reset (even counter-reset:none;) is applied to a top-level <ol>?


Solution

  • This is intentional, pending a spec clarification. (This behavior was implemented for Firefox 68.)

    Firefox lets your ol {counter-reset: some-counter} rule override the built-in UA style ol {counter-reset: list-item}, removing any special meaning of the ol wrt list numbering. As noted in the bug, you can specify both counters (ol {counter-reset: some-counter list-item;}) to fix this.

    ol {counter-reset: some-counter list-item;}
    li::before {
      content: "Marker should be: " counter(some-counter) ".";
      counter-increment: some-counter;
    }
    
    ol.alpha {list-style-type:lower-alpha;}
    ol.alpha > li::before{content: "Marker should be: " counter(some-counter, lower-alpha) ".";}
    <h2>List A</h2>
    <ol>
      <li>
        <ol>
          <li></li>
          <li></li>
          <li></li>
        </ol>
      </li>
      <li>
        <ol>
          <li></li>
          <li></li>
          <li></li>
        </ol>
      </li>
    </ol>
    
    <h2>List B</h2>
    <ol>
      <li>
        <ol class="alpha">
          <li></li>
          <li></li>
          <li></li>
        </ol>
      </li>
      <li>
        <ol class="alpha">
          <li style="counter-reset: some-counter"></li>
          <li></li>
          <li></li>
        </ol>
      </li>
    </ol>