Closed Bug 1841791 Opened 1 year ago Closed 1 year ago

CSS counter-reset doesn't reset the counter correctly

Categories

(Core :: Layout: Generated Content, Lists, and Counters, defect)

Firefox 115
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: ocavue, Assigned: emilio)

Details

Attachments

(6 files)

Attached file index.html

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36

Steps to reproduce:

Open https://codesandbox.io/s/firefox-counter-css-bug-mpt3fh or download the index.html file in this bug report. This webpage render a custom list item counter using counter-reset and counter-increment. The custom counter is between [ and ].

Actual results:

The result in Firefox is

[1] 1. A1
    [1] 1. B1
    [2] 2. B2
    [3] 3. B3
    [4] 4. B4
[5] 2. A2
[6] 3. A3

Notice that the counters before A2 and A3 are incorrect.

Expected results:

The result in Chrome and Safari is as following:

[1] 1. A1
    [1] 1. B1
    [2] 2. B2
    [3] 3. B3
    [4] 4. B4
[2] 2. A2
[3] 3. A3
Component: Untriaged → Layout: Generated Content, Lists, and Counters
Product: Firefox → Core

This is a bug in Chrome and Safari. We still have the old behavior behind the layout.css.counter-ancestor-scope.enabled=false pref, but the spec says to do what we do, see https://drafts.csswg.org/css-lists/#creating-counters, bug 1548753, https://wpt.fyi/results/css/css-lists, etc.

Status: UNCONFIRMED → RESOLVED
Closed: 1 year ago
Resolution: --- → INVALID

(In reply to Emilio Cobos Álvarez (:emilio) from comment #1)

This is a bug in Chrome and Safari. We still have the old behavior behind the layout.css.counter-ancestor-scope.enabled=false pref, but the spec says to do what we do, see https://drafts.csswg.org/css-lists/#creating-counters, bug 1548753, https://wpt.fyi/results/css/css-lists, etc.

If I add another A0 list item right above A1, I get the same behavior from Firefox, Safari and Chrome, show as below:

[1] 1. A0
[2] 2. A1
    [1] 1. B1
    [2] 2. B2
    [3] 3. B3
    [4] 4. B4
[3] 3. A2
[4] 4. A3

You can also see the screenshot between these two results here: https://github-production-user-asset-6210df.s3.amazonaws.com/24715727/251175475-12abe1b2-c845-44be-9fa0-4cbba0a55a52.png

Are both these two results are expected? I feel that there is a conflict in the behavior of the two.

In the first one there's A1s scope, which is the ancestor scope, while in the second one there's no ancestor scope because A1 matches li + li { counter-reset: none }. So behavior changes, but only because your CSS specifies it.

If you want to match <ol>s behavior but with a custom counter, the way to go about it is described in https://drafts.csswg.org/css-lists/#ua-stylesheet. So, something like:

li { counter-increment: my-list-counter; }
ol { counter-reset: list-item my-list-counter; }

That works, with valid markup, in all browsers. With invalid markup it only matches the HTML behavior on Firefox, that's the bug linked above.

Thank you for your explanation!

I kindly have another question, and I would greatly appreciate your assistance in providing an suggestion.

In fact I don't have two levels of DOM structure (i.e. `li` and `ol`), I only have one level of `div` elements. Here is code

```HTML
Attached file list-div
Thank you for your explanation!

I kindly have another question, and I would greatly appreciate your assistance in providing an suggestion.

In fact I don't have two levels of DOM structure (i.e. `li` and `ol`), I only have one level of `div` elements. Here is code
Attached file listdiv
Thank you for your explanation!

I have another question and would appreciate your suggestion. 

I have a single level of `div` elements instead of two levels of DOM structure (`li` and `ol`), so I cannot use the custom counter from https://drafts.csswg.org/css-lists/#ua-stylesheet. Is there anyway to achieve the same behavior as `<ol>` in this HTML structure?

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div.list-item {
            counter-set: my-list-counter;
            counter-reset: my-list-counter;
            counter-increment: my-list-counter;
            position: relative;
            margin-left: 100px;
        }

        div.list-item+div.list-item {
            counter-reset: none;
            counter-set: none
        }

        div.list-item:before {
            position: absolute;
            content: '[' counter(my-list-counter, decimal) ']';
            color: red;
            left: -40px
        }
    </style>
</head>

<body>
    <div class="list-item">
        <p>A1</p>
        <div class="list-item">
            <p>B1</p>
        </div>
        <div class="list-item">
            <p>B2</p>
        </div>
        <div class="list-item">
            <p>B3</p>
        </div>
        <div class="list-item">
            <p>B4</p>
        </div>
    </div>
    <div class="list-item">
        <p>A2</p>
    </div>
    <div class="list-item">
        <p>A3</p>
    </div>
</body>

</html>
```

Thank you for your explanation!

I have another inquiry, and I would be most grateful for your valuable suggestion.

We have a single level of div elements instead of two levels of DOM structure (li and ol), so I cannot use the custom counter from https://drafts.csswg.org/css-lists/#ua-stylesheet directly. Is there anyway to achieve the same behavior as <ol> in this HTML structure?

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div.list-item {
            counter-set: my-list-counter;
            counter-reset: my-list-counter;
            counter-increment: my-list-counter;
            position: relative;
            margin-left: 100px;
        }

        div.list-item+div.list-item {
            counter-reset: none;
            counter-set: none
        }

        div.list-item:before {
            position: absolute;
            content: '[' counter(my-list-counter, decimal) ']';
            color: red;
            left: -40px
        }
    </style>
</head>

<body>
    <div class="list-item">
        <p>A1</p>
        <div class="list-item">
            <p>B1</p>
        </div>
        <div class="list-item">
            <p>B2</p>
        </div>
        <div class="list-item">
            <p>B3</p>
        </div>
        <div class="list-item">
            <p>B4</p>
        </div>
    </div>
    <div class="list-item">
        <p>A2</p>
    </div>
    <div class="list-item">
        <p>A3</p>
    </div>
</body>

</html>

(Ah, it seems that I somehow submit the same comment for four times! It's my first time to use bugzilla and I'm not sure what went wrong. I couldn't find a button to delete my duplicate comment. I'm sorry for this)

So, I thought I had come up with a clever way of doing it with even less CSS. Just:

  div.list-item {
    contain: style;
    counter-increment: my-list-counter;
    position: relative;
    margin-left: 100px;
  }
  div.list-item::before {
    position: absolute;
    content: '[' counter(my-list-counter, decimal) ']';
    color: red;
    left: -40px
  }

But that doesn't work in Chrome / Safari :'(

I believe Firefox is right tho, as per https://drafts.csswg.org/css-contain-2/#property-scoped-to-a-sub-tree:

except the scoping element itself is counted as "outside" the tree

Chrome and Safari fail to do this afaict...

Firefox's rendering is correct, if I'm not holding this wrong, as per:

https://drafts.csswg.org/css-contain-2/#containment-style:

The counter-increment and counter-set properties must be scoped to the element’s sub-tree and create a new counter.

https://drafts.csswg.org/css-contain-2/#property-scoped-to-a-sub-tree:

the scoping element itself is counted as "outside" the tree, like the rest of the document, and the effects of the property on that element are unaffected by scoping.

I believe Chrome and Safari fail to implement that last bit.

Assignee: nobody → emilio

Thank you very such! Your code works like a charm! I didn't know I can use contain: style here.

I guess I could use @supports (-moz-appearance: none) to apply different rules to Firefox and other browsers as a workaround for now.

Well, Firefox is doing the right thing, so ideally you avoid hacking for Firefox and add the special-case for Chrome/WebKit instead. But... :)

😄 I will use @supports not (-moz-appearance: none) to add special-case for non-Firefix browsers.

A patch has been attached on this bug, which was already closed. Filing a separate bug will ensure better tracking. If this was not by mistake and further action is needed, please alert the appropriate party. (Or: if the patch doesn't change behavior -- e.g. landing a test case, or fixing a typo -- then feel free to disregard this message)

Flags: needinfo?(emilio)

The patch is just a test for an issue that was here (https://bugs.chromium.org/p/chromium/issues/detail?id=1462328). So seems appropriate to use this bug to land it? I'm happy to file a different one too I guess, it's just that it didn't seem worth it...

Flags: needinfo?(emilio)

(In reply to Emilio Cobos Álvarez (:emilio) from comment #16)

The patch is just a test for an issue that was here (https://bugs.chromium.org/p/chromium/issues/detail?id=1462328). So seems appropriate to use this bug to land it?

Yup, this is fine, per the parenthetical at the end comment 15. ("e.g. landing a test case")

Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/f9c12557d7a4
Add a WPT for the counter scoping issue mentioned in comment 9. r=dholbert
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/41162 for changes under testing/web-platform/tests
Upstream PR merged by moz-wptsync-bot
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: