Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-lists-3] Should automatic list-item increment adjust for ol[reversed]? #4181

Closed
fantasai opened this issue Aug 8, 2019 · 16 comments · Fixed by #6096
Closed

[css-lists-3] Should automatic list-item increment adjust for ol[reversed]? #4181

fantasai opened this issue Aug 8, 2019 · 16 comments · Fixed by #6096
Labels
css-lists-3 Current Work HTML Requires coordination with HTML people

Comments

@fantasai
Copy link
Collaborator

fantasai commented Aug 8, 2019

The list-item counter is defined to automatically increment by one on each element with display: list-item. (See #3686 for how that works.) <ol reversed> lists need to have a list-item increment of -1.

Should this be done by magic interactions with the host language, or should the UA style sheet simply include ol[reversed] > li { counter-increment: list-item -1; }?

@tabatkins
Copy link
Member

It doesn't work thru the UA stylesheet:

  • That requires that it show up in the serialization of the computed value of 'counter-increment', which no browser does, and which Firefox tried to do but backed off from. (Well, I think they just tried to do the normal incrementing, but it seems weird for ol to influence counter-increment sometimes but not other times.)
  • It means that any non-initial value for counter-increment needs to explicitly reproduce the 'list-item' behavior. I don't think it's reasonable to allow people to ignore 'list-item' for the CSS inherent behavior, but require them to pay attention to it for the HTML inherent behavior.

@fantasai
Copy link
Collaborator Author

fantasai commented Aug 8, 2019

As a general principle, I prefer to minimize the amount of magic in CSS that depends on document semantics: if we can describe HTML's behavior using CSS mechanisms, where HTML's interaction is limited to injecting regular CSS declarations into the cascade rather than applying specialized knowledge of the HTML vocabulary during layout / at used-value time, I think that's better.

Let's be clear the issue here isn't about list-item increments in general: the default increment that we apply to list-item display types works fine for HTML list numbering in almost all cases. The exception is for reversed lists, and I think it's fine to handle that through the UA style sheet. I don't think it's factual to say that it "doesn't work": it clearly does work, and there aren't, as far as I am aware, any web-compat concerns with doing it that way.

If there's a problem with reversing list numbering through a rule like ol { counter-increment: list-item -1; }, then I think we should take @FremyCompany's suggestion in #3686 (comment) and introduce a property to control the automatic increment, e.g. ol { list-increment: -1; }. But I think reversed lists are unusual enough that just using counter-increment rule should be sufficient.

CC @MatsPalmgren @dbaron @domenic

@tabatkins
Copy link
Member

If we want to explain the magic via a brand new property (which wouldn't have cascading or backcompat problems), that's fine. I don't think it's useful enough to be worth doing, but whatever; I'm not opposed.

But I don't like the idea that you can definitely set counter-increment: foo 1; on a normal li and it'll continue to number itself perfectly correctly, but if that li is in an <ol reversed> you'll screw up the numbering.

Either both forward and reverse numbers should work magically, regardless of what other stuff you set in counter-increment, or both should fail to work, imo.

@emilio
Copy link
Collaborator

emilio commented Aug 8, 2019

The issue why you can't do ol[reversed]>li is because it's not li what you should target, but "anything with a computed display value of list-item".

@emilio
Copy link
Collaborator

emilio commented Aug 8, 2019

Also need to be arbitrary descendants. So in this case, while unfortunate, it needs to be through magic. In Gecko that magic is a -moz-list-reversed inherited property, see:

https://searchfox.org/mozilla-central/rev/9775cca0a10a9b5c5f4e15c8f7b3eff5bf91bbd0/layout/style/res/html.css#582

We could standardize it, but I think I agree with Tab that it seems to have limited utility.

@FremyCompany
Copy link
Contributor

If a controlling property already exists, we probably should standardize it. Otherwise that behavior would remain unexplained in the spec.

@tabatkins
Copy link
Member

It's not unexplained if the spec explains it in sufficient detail. ^_^

@MatsPalmgren
Copy link

(Just to clarify, -moz-list-reversed is a Gecko internal property that isn't exposed to web content, so it's merely an implementation detail.)

If we add support for reversed lists in CSS then I think we should consider generalizing it to all counters. There would actually be some utility in that for authors, since the most important aspect of <ol reversed> is that the start ordinal is automatic based on the content. That can't be achieved for other counters currently.

Also, a new inherited property might not be the best way to add this feature. It was convenient to implement it like that when the automatic counter-increment for list items was a computed value, but #3686 changed that to used-value time, so we could probably remove this property now. (It might be better to extend counter-reset in some way instead, if we standardize this.)

@dbaron dbaron changed the title [css-lists-3] Should automatic list-item increment adjust for ol[reversted]? [css-lists-3] Should automatic list-item increment adjust for ol[reversed]? Aug 10, 2019
@tabatkins
Copy link
Member

The problem is that we're barred from the obvious methods of extending counter-reset, due to the historical lack of commas. counter-reset: foo reversed;, for example, just resets two counters, foo and reversed.

We could do more complex stuff, like stuffing new values into a function or something.

@tabatkins
Copy link
Member

If we were to consider that, tho, hmmm. We've talked before about having a way to count the number of children an element has, and use that to initialize counter-reset for reversed lists. But as Emilio points out, that's not actually sufficient; arbitrary descendants can use that list counter.

So I'm thinking the way to go is to iterate thru all the elements in the scope, counting the display:list-item elements that have the counter in question in scope (that is, it's the last counter of that name in the element's counter set, and thus possible to be set/incremented by them). That's pretty magic, but I think it's the degree of magic we need to achieve this functionality.

@fantasai
Copy link
Collaborator Author

@tabatkins Please file a separate issue on the start value of reversed lists. This issue is about increments specifically (and intentionally).

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Should automatic list-item increment adjust for ol[reversed]?.

The full IRC log of that discussion <dael> Topic: Should automatic list-item increment adjust for ol[reversed]?
<dael> github: https://github.com//issues/4181
<dael> TabAtkins: If we can achieve through UA stylesheet or do magic. Magic to host language or in css
<dael> TabAtkins: emilio points out [missed]
<dbaron> q+
<dael> fantasai: We have normal lists, they're great. We have reversed lists where increment is -1. Where you start is sept. Each li decrements counter needs to be implement. Only magic is that it's incremented by 1 on list item box
<fantasai> ol[reversed] > li { counter-increment: list-item -1; }
<dael> fantasai: Put in spec you can do on UA stylesheet. Works in general easy case. HTML spec includes any box with display of list-item in the numbering and excluses non-list-items. If you put a div in the li and give that a display: list-item it increments. THe list relies on the CSS
<dael> fantasai: You can't reflect the current behavior. I can try and share a test case
<TabAtkins> aka the [reversed] behavior is *literally* just "do normal list item numbering, then reverse all the numbers"
<dael> fantasai: 3 things we can do. 1) use UA stylesheet and get impl to do something different that doesn't account for display value of boxes. 2) have magic and host lang can change magic. 3) create css property that says what magic increment is
<fantasai> Behavior of li counting in HTML https://html.spec.whatwg.org/multipage/grouping-content.html#the-li-element
<dael> dbaron: I think there are a bunch of edge cases that suggest modeling this as a decrement is wrong approach. 2 ways to model. starting value is magic, items decremenet, counter goes forward. Other is counter counts from end to beginning. This is different results at times, like if you change counter in the middle
<fantasai> http://software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Col%20reversed%3E%0A%3Cli%20style%3D%22border%3A%20solid%22%3E%20x%3Cdiv%20style%3D%22display%3A%20list-item%22%3ETest%3C%2Fdiv%3E%0A%3Cli%3E%20y%0A%3Cli%3E%20z%0A%3C%2Fol%3E%0A
<dael> dbaron: Tend to think modeling this as magic to get the beginning and then decrements will get wrong result in a bunch of cases
<dael> TabAtkins: You think counting backwards and interacting with counter-set is good?
<dael> dbaron: I'm looking at browser behavior and actual behavior of value attribute with reverse is not sensible or interop
<dael> dbaron: Maybe value is already broken and other way is right
<dael> TabAtkins: Something odd in FF. FF and Chrome agree value effects following things and not proceeding. Differences in what number the very first item starts in. They agree it's count forward
<dael> dbaron: Maybe stuck with wrong model
<dael> TabAtkins: Both models have arguments. Fine with either
<dael> fantasai: Did run a test with decrement as -2 and it starts counting into negative numbers. Start number was no adjusted to account for that
<fantasai> http://software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Cstyle%3Eli%20%7B%20counter-increment%3A%20list-item%20-2%3B%20%7D%3C%2Fstyle%3E%0A%3Col%20reversed%3E%0A%3Cli%20style%3D%22border%3A%20solid%22%3E%20x%3Cdiv%20style%3D%22display%3A%20list-item%22%3ETest%3C%2Fdiv%3E%0A%3Cli%3E%20y%0A%3Cli%3E%20z%0A%3C%2Fol%3E%0A
<TabAtkins> http://software.hixie.ch/utilities/js/live-dom-viewer/saved/7121
<TabAtkins> Dunno why Firefox starts numbering at 7 even tho there are only six items.
<dael> Rossen_: From the 3 choices at the beginning seems like we're getting to none of them?
<dael> TabAtkins: Aside from that my test shows a weird start number, browsers seem consistent in how they treat things
<dael> TabAtkins: Figure out value of last item that would incremement, use that as the first value. Figure out magic value where if nothing screws with numbering gets you to 1 and then start at that ind do minus 1
<dael> TabAtkins: I'm on side of UA magic so there's interop I don't believe css needs to control on it's own.
<dael> dbaron: html editors might be unhappy. html editors seem unhappy that css claims their stylesheets are doing wrong thing
<dael> TabAtkins: [missed] reverse engineering at the time and we're saying do this with css now. Seeing you got no bugs I think we're fine and we can do this
<dael> fantasai: Still not clear on how reverse is supposed to work.
<dael> fantasai: Would liek to get updated draft published b/c cleaned up counters section substanitally. WE should publish and mark reverse lists as an open issue.
<dael> fantasai: Should we publish draft with previous state or should we publish with the concept of the magic increment? SHould leave issue open, but what to publish with
<dael> fantasai: Inclination is publish no change from previous b/c that's clear we have not solved and update later after we conclude
<dael> Rossen_: Do you want to discuss next before publish?

@faceless2
Copy link

faceless2 commented Aug 16, 2019

Regarding setting the initial value of a reversed list, I'd originally felt you could do this in pure CSS with a new function count(), which takes a selector and returns the number of elements that match it when evaluated on the current node: so exactly the same as :has(), but returning an ordinal value.

You could have something like:

ol[reversed] {
    counter-reset: list-item calc(attr(start integer, count(> li)) + 1);
}

However the comment from @emilio above, that this must count the items with display:list-item not just li, made me think believe it couldn't work. But its just dawned on me that it can, like so:

ol[reversed] {
    counter-reset: list-item calc(attr(start integer, count(> ::marker)) + 1);
}

There are numerous uses for a count() function in CSS - imagine the javascript-free layouts you could create, using only calc, count and the new trignometric functions going into css-values.

@fantasai
Copy link
Collaborator Author

fantasai commented Aug 17, 2019

If we aren't dealing with a Web-compat issue over numbering list-item descendants of an ol[reversed] that aren't li elements, I think my preference here would be to define a list-increment property that increments a list-item counter but only on display: list-item boxes.

Then the UA style sheet can say ol[reversed] > li { list-increment: -1; }⁠—and also anyone who wants to turn off the increment can write X { list-increment: none; }, which would not disturb any counter-increment declarations or instantiate a superfluous list-item counter (that might then show up in li:marker { content: counters(list-item, ".") }, which is a little nice.

Wrt Web-compat, I don't think structures like the following are particularly common? This is what would change⁠—because we wouldn't be reversing the numbering on that DIV.

<ol reversed>
  <li>three
      <div style="display: list-item">two</div>
   <li>one
</ol>

@MatsPalmgren
Copy link

@fantasai I agree there's probably not much of a web-compat problem with arbitrary descendant non-<li> elements styled as display:list-item. But the issue is that <li>s might be wrapped, like so:

<ol reversed>
  <font>
    <li>A</li>
    <li>B</li>
    <li>C</li>
  </font>
</ol>

I suspect that's common enough that we need to handle it and your ol[reversed] > li rule above wouldn't work for this case. (Also, that rule would give a non-default computed value for <ol reversed><li style="display:block"> which seems unfortunate, but probably doesn't matter in practice.)

I still think implementing this as a preshint that maps <ol reversed> to counter-reset: reversed(list-item) or some such and making that imply a default counter-increment value of -1 in layout is the best solution.

@fantasai fantasai added the HTML Requires coordination with HTML people label Nov 17, 2020
zcorpan added a commit to bocoup/csswg-drafts that referenced this issue Mar 11, 2021
This allows HTML to define the rendering for `<ol reversed>` in terms
of a presentational hint for `counter-reset: reversed(list-item)`
or `<ol reversed start=X>` to `counter-reset: reversed(list-item) X+1`.
See whatwg/html#4816

Fixes w3c#4181
Fixes w3c#4211
zcorpan added a commit to bocoup/csswg-drafts that referenced this issue Mar 11, 2021
This allows HTML to define the rendering for `<ol reversed>` in terms
of a presentational hint for `counter-reset: reversed(list-item)`
or `<ol reversed start=X>` to `counter-reset: reversed(list-item) X+1`.
See whatwg/html#4816

Fixes w3c#4181
Fixes w3c#4211
@zcorpan
Copy link
Member

zcorpan commented Mar 11, 2021

See PR #6096 for a proposal to address this (and discussion in #4211).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-lists-3 Current Work HTML Requires coordination with HTML people
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants