You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-lists] CSS counter scope/inheritance is incompatible with HTML ordinals #5477
Gecko has implemented HTML <ol><ul><li> ordinals using the built-in list-item counter as per the CSS Lists spec. However, we've got many reports that this breaks existing web content to the extent that we need to ship a (non spec-compliant) fix.
Consider this simple HTML example:
According to CSS Lists, the correct rendering is:
This is clearly not how HTML lists should work - the last item should have the ordinal 3.
Granted, the above HTML is invalid - <ol><ul> aren't allowed as a direct child of <ol><ul>, but this kind of bogus markup is rather common on the web unfortunately. It's also the DOM that execCommand('indent') produce (sigh), which affects HTML editors. So telling authors to fix their markup isn't a tenable solution.
The alternative fixes we considered were:
change CSS Lists to make all CSS counters behave differently for this case
Con: breaks existing (author-specified) nested CSS counters of the same name
change the behavior for the built-in list-item counter only
Con: makes the built-in list-item and other CSS counters behave differently which is a more complicated model to implement, specify, and teach to authors
extend CSS Lists to allow either behavior
(e.g. something like ol, ul, menu { counter-reset: strict-scope(list-item); } in the UA sheet)
Con: a more complicated model to implement, specify, and teach to authors
We concluded that 1 is the least bad solution, so we propose to include a new step in finding the counter scope that searches an element's ancestors first, before falling back to the current steps in the spec that searches previous siblings in reverse DOM order.
This also makes author-defined counters behave more sensible - consider the analogous example:
Slightly nervous about this one. Can I propose a fourth option which might be lower impact?
Change the counter rules so that counter-reset is applied aftercounter-increment and counter-set (it's currently applied before). Then you can cater for the invalid markup with this in a UA sheet.
The outer-scoped list-item will be incremented, then a new scope is created with the counter value of 1.
The only impact that would have is on elements that have both a counter-reset and counter-increment - a pointless combination as the rules are currently defined (and also one that can be searched for to see how often its used). It feels like this approach might have less unintended side-effects (and be easier to explain too).
The outer-scoped list-item will be incremented, then a new scope is created with the counter value of 1.
@faceless2 If counter-reset: list-item is applied afterwards, then the inner scope will have value 0. And if counter inheritance prefers the previous sibling over the parent, the next element will still get the value from the inner scope? I don't get how your proposal solves the problem.
The CSS Working Group just discussed [css-lists] CSS counter scope/inheritance is incompatible with HTML ordinals, and agreed to the following:
RESOLVED: change CSS Lists to make all CSS counters behave differently for this case
The full IRC log of that discussion
<emilio> Topic: [css-lists] CSS counter scope/inheritance is incompatible with HTML ordinals
<emilio> github: https://github.com//issues/5477
<emilio> TabAtkins: when I was writing the counter rules I was working from css 2.1 and my testing
<emilio> ... I knew HTML <ol> didn't match CSS counters in invalid markup
<emilio> ... Gecko tried to switch to counters for CSS lists
<emilio> ... and found out that they were not web compatible
<emilio> ... see the example in the issue with a nested <ol> directly under another
<emilio> ... html renders that as you'd probably expect
<emilio> ... that's also what editors generate for some reason
<emilio> ... In order to fix it we can specify that either html is magic
<emilio> ... that the list-item counter is magic
<emilio> ... or switch counter behavior
<emilio> ... mats is going for the later
<Rossen_> q
<emilio> ... and is proposing to do an ancestor-only check and only if that fails we look for a previous sibling counter
<emilio> ... that's probably fine and would still work with the main sibling use case which is naming headers
<emilio> ... so I'm ok with making that change
<emilio> Rossen_: you're referring to the third approach in the comment?
<emilio> TabAtkins: no, number 1
<dbaron> seems like a reasonable way to fix this without breaking use of counter numbering for headers
<emilio> fantasai: if you look at the example and replace list with section and item with h1, it will end up giving a better result
<emilio> ... I'm in favor of this change
<Rossen_> ack fantasai
<emilio> ... if we can pull it of
<emilio> off
<emilio> q+
<astearns> and you’re OK with this, faceless2?
<fantasai> emilio: We actually have made this change, unsure if released yet
<fantasai> emilio: but haven't heard of any breakage
<fantasai> Rossen_: cool
<faceless2> yes. everything I had to say on the topic before was wrong :-)
<emilio> Rossen_: objections?
<fantasai> strong +1 given emilio's report :)
<emilio> RESOLVED: change CSS Lists to make all CSS counters behave differently for this case
<emilio> [... discussion about republishing CSS2 ...]
<oriol> The change is in Firefox 82, which seems it was released on 2020-10-20 (but I still don't have it)
Yes, I would again say that Firefox seems right since that's how CSS counters behave, and Blink agrees with ::marker { content: counter(list-item) ". " }.
Yes, Firefox is correct. The 1st <li> instantiates the list-item counter, which is propagated to descendants, following siblings, and descendants of following siblings. It's not propagated to following uncles, so the 3rd <li> creates a new instance. If you want all the items to share the same instance of the counter, you can use body { counter-reset: list-item } (or a <ol> wrapper)
I was surprised that the latest Chrome (126 and later) does not work as expected, while Firefox and Safari work as expected, and I thought it is a bug in Chromium. Then I found this CSS issue.
I believe that reverting the spec change is the right decision, and I hope that all browsers will behave consistently.
Changed counter inheritance to take from the parent first, and only take from the sibling if it’s a new counter.
But Example 22 in the spec conflicts with the spec. In the example, the last h2's counter does not inherit from the parent element, so the last h2 render like this:
As we have reverted the spec, so the test results of Firefox and Safari are correct?
<styletype="text/css">#test { counter-reset: c; }
#testspan { counter-increment: c; }
#testspan::before { content:counter(c, decimal-leading-zero); }
</style><p>The following two lines should look the same:</p><divid="test"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><spanstyle="counter-reset: c 98"></span><span></span><span></span></div>
Chrome inherits from the parent element:
01 02 03 04 05 06 07 08 09 10 11 12 99 13 14
Firefox and Safari inherit from the sibling element:
Yes, but Firefox seems to have a special behavior for list-item (which is odd given that Mats argued against "change the behavior for the built-in list-item counter only")
Activity
faceless2 commentedon Aug 27, 2020
Slightly nervous about this one. Can I propose a fourth option which might be lower impact?
counter-resetis applied aftercounter-incrementandcounter-set(it's currently applied before). Then you can cater for the invalid markup with this in a UA sheet.The outer-scoped list-item will be incremented, then a new scope is created with the counter value of 1.
The only impact that would have is on elements that have both a
counter-resetandcounter-increment- a pointless combination as the rules are currently defined (and also one that can be searched for to see how often its used). It feels like this approach might have less unintended side-effects (and be easier to explain too).[css-lists] Prefer an ancestor's counter scope over a sibling's scope.
Bug 1548753 - [css-lists] Prefer an ancestor's counter scope over a s…
[css-lists] Prefer an ancestor's counter scope over a sibling's scope.
Loirooriol commentedon Sep 1, 2020
@faceless2 If
counter-reset: list-itemis applied afterwards, then the inner scope will have value 0. And if counter inheritance prefers the previous sibling over the parent, the next element will still get the value from the inner scope? I don't get how your proposal solves the problem.faceless2 commentedon Sep 2, 2020
I've just worked through it again. I'm wrong and you're correct. Scratch that idea, sorry!
Bug 1548753 - [css-lists] Prefer an ancestor's counter scope over a s…
css-meeting-bot commentedon Oct 22, 2020
The CSS Working Group just discussed
[css-lists] CSS counter scope/inheritance is incompatible with HTML ordinals, and agreed to the following:RESOLVED: change CSS Lists to make all CSS counters behave differently for this caseThe full IRC log of that discussion
<emilio> Topic: [css-lists] CSS counter scope/inheritance is incompatible with HTML ordinals<emilio> github: https://github.com//issues/5477
<emilio> TabAtkins: when I was writing the counter rules I was working from css 2.1 and my testing
<emilio> ... I knew HTML <ol> didn't match CSS counters in invalid markup
<emilio> ... Gecko tried to switch to counters for CSS lists
<emilio> ... and found out that they were not web compatible
<emilio> ... see the example in the issue with a nested <ol> directly under another
<emilio> ... html renders that as you'd probably expect
<emilio> ... that's also what editors generate for some reason
<emilio> ... In order to fix it we can specify that either html is magic
<emilio> ... that the list-item counter is magic
<emilio> ... or switch counter behavior
<emilio> ... mats is going for the later
<Rossen_> q
<emilio> ... and is proposing to do an ancestor-only check and only if that fails we look for a previous sibling counter
<emilio> ... that's probably fine and would still work with the main sibling use case which is naming headers
<emilio> ... so I'm ok with making that change
<emilio> Rossen_: you're referring to the third approach in the comment?
<emilio> TabAtkins: no, number 1
<dbaron> seems like a reasonable way to fix this without breaking use of counter numbering for headers
<emilio> fantasai: if you look at the example and replace list with section and item with h1, it will end up giving a better result
<emilio> ... I'm in favor of this change
<Rossen_> ack fantasai
<emilio> ... if we can pull it of
<emilio> off
<emilio> q+
<astearns> and you’re OK with this, faceless2?
<fantasai> emilio: We actually have made this change, unsure if released yet
<fantasai> emilio: but haven't heard of any breakage
<fantasai> Rossen_: cool
<faceless2> yes. everything I had to say on the topic before was wrong :-)
<emilio> Rossen_: objections?
<fantasai> strong +1 given emilio's report :)
<emilio> RESOLVED: change CSS Lists to make all CSS counters behave differently for this case
<emilio> [... discussion about republishing CSS2 ...]
<oriol> The change is in Firefox 82, which seems it was released on 2020-10-20 (but I still don't have it)
29 remaining items
Loirooriol commentedon Aug 1, 2024
That's an HTML concept that seems only relevant for non-CSS UAs. CSS UAs need to obey https://drafts.csswg.org/css-lists/#content-property, so in this case the text comes from the
list-itemcounter. And as per https://html.spec.whatwg.org/multipage/rendering.html#lists, only<ol>,<ul>and<menu>default tocounter-reset: list-item.zp1996 commentedon Aug 4, 2024
@Loirooriol This test case is failed on Firefox. Is Firefox's behavior correct based on the above description?
Chromium/Webkit:


Firefox:
Loirooriol commentedon Aug 5, 2024
Yes, I would again say that Firefox seems right since that's how CSS counters behave, and Blink agrees with
::marker { content: counter(list-item) ". " }.zp1996 commentedon Aug 6, 2024
@Loirooriol Is the behavior of this test correct in Firefox?
actual result:


IMO, expected result:
Loirooriol commentedon Aug 6, 2024
Yes, Firefox is correct. The 1st
<li>instantiates thelist-itemcounter, which is propagated to descendants, following siblings, and descendants of following siblings. It's not propagated to following uncles, so the 3rd<li>creates a new instance. If you want all the items to share the same instance of the counter, you can usebody { counter-reset: list-item }(or a<ol>wrapper)yisibl commentedon Aug 16, 2024
Is this the same issue? https://issues.chromium.org/issues/359623686
MurakamiShinyu commentedon Aug 17, 2024
I think so. I encountered this problem when testing a stylesheet that uses
counters()for nested section numbering, as shown in the following example:(CodePen: https://codepen.io/MurakamiShinyu/pen/KKjZVbR )
I was surprised that the latest Chrome (126 and later) does not work as expected, while Firefox and Safari work as expected, and I thought it is a bug in Chromium. Then I found this CSS issue.
I believe that reverting the spec change is the right decision, and I hope that all browsers will behave consistently.
zp1996 commentedon Sep 19, 2024
According to recent changes around counter inheritance in the spec:
But Example 22 in the spec conflicts with the spec. In the example, the last
h2's counter does not inherit from the parent element, so the lasth2render like this:A comparable issue: #10491
IMO, we need to update the spec to clarify the behavior.
Loirooriol commentedon Sep 19, 2024
These changes need to be reverted as resolved in #5477 (comment)
zp1996 commentedon Sep 20, 2024
As we have reverted the spec, so the test results of Firefox and Safari are correct?
Chrome inherits from the parent element:
Firefox and Safari inherit from the sibling element:
Loirooriol commentedon Sep 21, 2024
Yes, but Firefox seems to have a special behavior for
list-item(which is odd given that Mats argued against "change the behavior for the built-inlist-itemcounter only")emilio commentedon Sep 21, 2024
Yeah, I changed that in https://bugzilla.mozilla.org/show_bug.cgi?id=1885842 because we kept getting issues like that.
Bug 1548753 - [css-lists] Prefer an ancestor's counter scope over a s…
[css-lists-3] Revert "Change counter inheritance to only take from pr…