Skip to content

[css-lists] How should spaces be treated in markers? #4448

Closed

Description

@Loirooriol

The white-space property doesn't apply to markers, but how do spaces behave in markers?

Consider

<ol>
  <li class="marker default inside space-1">-</li>
  <li class="marker default inside space-2">-</li>
  <li class="marker default inside space-n">-</li>
  <li class="marker default outside space-1">-</li>
  <li class="marker default outside space-2">-</li>
  <li class="marker default outside space-n">-</li>
  <li class="marker pre inside space-1">-</li>
  <li class="marker pre inside space-2">-</li>
  <li class="marker pre inside space-n">-</li>
  <li class="marker pre outside space-1">-</li>
  <li class="marker pre outside space-2">-</li>
  <li class="marker pre outside space-n">-</li>
  <li class="type default inside space-1">-</li>
  <li class="type default inside space-2">-</li>
  <li class="type default inside space-n">-</li>
  <li class="type default outside space-1">-</li>
  <li class="type default outside space-2">-</li>
  <li class="type default outside space-n">-</li>
  <li class="type pre inside space-1">-</li>
  <li class="type pre inside space-2">-</li>
  <li class="type pre inside space-n">-</li>
  <li class="type pre outside space-1">-</li>
  <li class="type pre outside space-2">-</li>
  <li class="type pre outside space-n">-</li>
</ol>
ol { font-family: monospace}
.pre { white-space: pre }
.inside { list-style-position: inside }
.marker.space-1::marker { content: 'a b' }
.marker.space-2::marker { content: 'a  b' }
.marker.space-n::marker { content: 'a\a b' }
.type.space-1 { list-style-type: 'a b' }
.type.space-2 { list-style-type: 'a  b' }
.type.space-n { list-style-type: 'a\a b' }

The results in Firefox, Chromium legacy and Chromium with LayoutNG and look like

          | Firefox   | Chrome leg| Chrome NG |
| ------- | --------- | --------- | --------- |
| marker  |     a b-  |     1. -  |     1. -  |
| default |     a b-  |     2. -  |     2. -  |
| inside  |     a b-  |     3. -  |     3. -  |
| ------- | --------- | --------- | --------- |
| marker  |  a b-     |  4. -     |  4. -     |
| default |  a b-     |  5. -     |  5. -     |
| outside |  a b-     |  6. -     |  6. -     |
| ------- | --------- | --------- | --------- |
| marker  |     a b-  |     7. -  |     7. -  |
| pre     |     a  b- |     8. -  |     8. -  |
| inside  |     a     |     9. -  |     9. -  |
|         |     b-    |           |           |
| ------- | --------- | --------- | --------- |
| marker  |  a b-     | 10. -     | 10. -     |
| pre     | a  b-     | 11. -     | 11. -     |
| outside |    a      | 12. -     | 12. -     |
|         |    b-     |           |           |
| ------- | --------- | --------- | --------- |
| type    |     a b-  |     a b-  |     a b-  |
| default |     a  b- |     a  b- |     a b-  |
| inside  |     ab-   |     a b-  |     a b-  |
| ------- | --------- | --------- | --------- |
| type    |  a b-     |  a b-     |  a b-     |
| default | a  b-     | a  b-     | a  b-     |
| outside |   ab-     |  a b-     |    a      |
|         |           |           |    b-     |
| ------- | --------- | --------- | --------- |
| type    |     a b-  |     a b-  |     a b-  |
| pre     |     a  b- |     a  b- |     a  b- |
| inside  |     ab-   |     a b-  |     a     |
|         |           |           |     b-    |
| ------- | --------- | --------- | --------- |
| type    |  a b-     |  a b-     |  a b-     |
| pre     | a  b-     | a  b-     | a  b-     |
| outside |   ab-     |  a b-     |    a      |
|         |           |           |    b-     |

That is:

  • In Firefox,
    • ::marker's content obeys the white-space property inherited from the list-item.
    • list-style-type ignores white-space, and
      • spaces are preserved
      • newlines are removed (really removed, not just collapsed)
    • Presumably list-style-type will obey white-space after https://bugzil.la/1542807
  • In Chromium with legacy layout,
    • ::marker is not supported
    • list-style-type ignores white-space, and
      • spaces are preserved
      • newlines are collapsed into spaces.
  • In Chromium with LayoutNG,
    • ::marker is not supported
    • For inside positioning, list-style-type obeys the white-space property inherited from the list-item
    • For outside positioning, list-style-type uses white-space: pre

What's the expected behavior?

Activity

  1. faceless2 commented on Oct 24, 2019

    @faceless2

    Three observations on this:

    1. If spaces are in ::marker, they're there because the stylesheet explicitly listed them, either in the content property or in @counter-style. Trailing spaces (one or more) are also used to separate the marker from the content. So whitespace should definitely not be collapsed, at least not by default, which means inheriting white-space from the parent is not an option. At the very least you'd need a user-agent rule like ::marker { white-space: N }, or functional equivalent.

    2. Markers are aligned against the first in-flow linebox descendent of the list-item - so if the list-item's first child is a block, for example, it's that child's linebox. I can't find my notes on this right now but I am pretty certain they also contribute to the height of that linebox - i.e. the initial list-item linebox is as at least as high as the marker. For this reason I think allowing newlines might prove problematic; you're then effectively trying to size a linebox to accomodate content which is already multiline. Until I can recall the tests that will back me up on this point, I'm prepared to be corrected on this one.

    3. inside positioning just generates a regular inline, so poses no more problem for white-space than any other inline. Inside markers should probably be considered separately to outside markers.

    So if removing newlines does prove critical, you can't allow the user to override white-space on the ::marker, in case they try to keep newlines.

    (edit: this is on the presumption that list-style-type is, or will be, implemented as a ::marker)

  2. MatsPalmgren commented on Nov 9, 2019

    @MatsPalmgren

    The white-space property doesn't apply to markers ...

    The styling restrictions on ::marker should be removed IMO. There's no reason whatsoever that ::marker can't support the same properties as ::before/::after does. (with some minor restrictions on display/position values for outside markers perhaps)

  3. MatsPalmgren commented on Nov 9, 2019

    @MatsPalmgren

    Replying to @faceless2 points above:

    1. If spaces are in ::marker, they're there because the stylesheet explicitly listed them

    True, but it's also trivial for authors to use a non-collapsing space if that's what they want: \A0.

    1. Markers are aligned against the first in-flow linebox descendent of the list-item

    Currently, outside markers are aligned outside the inline/block start/start edge but I think we should enable authors to align the marker elsewhere in the future, for example ::marker { align-self:center/end } to align it in the block-axis. I think it would be a mistake for the spec to assume that these lineboxes are always going to be edge-to-edge like they currently are.

    ... I am pretty certain they also contribute to the height of that linebox - i.e. the initial list-item linebox is as at least as high as the marker

    That doesn't preclude supporting multi-line markers though. We could use the first linebox in the marker to implement that legacy behavior.

    1. inside positioning just generates a regular inline

    Agreed, an inside marker should just be a normal inline box by default. I'm strongly in favor of allowing authors to style it with display etc though, to achieve whatever layout they want.

  4. MatsPalmgren commented on Nov 9, 2019

    @MatsPalmgren

    I tend to think that trailing spaces should collapse. That's consistent with how this behaves:

    <style>
    div::before { content: '::before '; display: inline-block; }
    </style>
    <div>item</div>

    As I suggested in #3771, we should consider an outside ::marker box as having a blockified display value. The collapsing behavior falls out from that without adding any special rules.

  5. Loirooriol commented on Nov 9, 2019

    @Loirooriol
    ContributorAuthor

    There's no reason whatsoever that ::marker can't support the same properties as ::before/::after does.

    I'm not that sure about non-inherited properties. But I tend to agree for inherited properties (except list-style-* I guess). The restriction can be bypassed anyways by setting the desired marker value to the list-item, let the marker inherit it, wrap the list-item contents inside some container, and reset the value in that container. But this sucks for authors.

    it's also trivial for authors to use a non-collapsing space if that's what they want: \A0.

    The point is that @counter-style is being used on the wild, with the expectation that spaces won't collapse. Changing the behavior to no longer collapse by default would break existing code.

    Also, IMO using U+00A0 is semantically wrong, non-breaking spaces are supposed to be used to avoid breaks between specific pairs of words, not to avoid whitespace collapsing (I know it's a lost battle, but still). The proper way to control whitespace collapsing is the white-space property.

    So I tend to think

    • We should settle on some default value for white-space in markers (pre?) and assign it in UA origin.

    • This default value may depend on whether the marker is inside or outside, e.g.

      ::marker:inside-marker { white-space: inherit }
      ::marker:outside-marker { white-space: pre }

      where :inside-marker and :outside-marker would be internal pseudo-classes that can only be used in UA origin (not exposed to the web).
      But probably it's simpler to always have the same default value.

    • Decide what to do with multiline markers.

    • At some point, let authors customize marker's white-space (among other properties) with their desired value.

  6. faceless2 commented on Nov 10, 2019

    @faceless2

    Markers are separated from the body of the list with white-space. If you collapse that away by default, a space character in counter-suffix becomes useless. At the very least you're going to have to redefined the default value of counter-suffix to '\00A0', and if users are setting their own counter-suffix then things will probably break.

    (Incidentally, although Safari currently doesn't support @counter-style yet, bullets are separated from the body with two spaces.)

    Re. the marker alignment, you've already got https://drafts.csswg.org/css-lists-3/#marker-side which allows a little control. @MatsPalmgren, does this cover the case you had in mind?

    My main concern with block-axis marker positions, multi-line markers etc is that the css-lists modules seems to have had considerably less love than it deserves. List bullets were first described in HTML 1, and from what I can see browsers haven't changed much in the way they position them since then.

    • Only Firefox is shipping support for @counter-style
    • Firefox, Chrome and Safari implement counter-style: disc with some sort of custom circle rather than the U+2022 bullet character suggested (although not required) in css-counters-3. Effectively, this means font-family isn't useful with counter-style: disc. Same for circle and square.
    • list markers do contribute to the height of their corresponding list body, but the exact mechanism for this still isn't defined and varies across browsers (see https://jsbin.com/sasuzig/edit?html,output). This behaviour is different to a regular inline-block

    My point is there seems to be relatively little appetite (for both the specification and implementations) to move forward. For that to change, I'd be inclined to severely limit the scope of what markers can do - at least for css-lists-1.

  7. Loirooriol commented on Nov 10, 2019

    @Loirooriol
    ContributorAuthor

    although Safari currently doesn't support @counter-style yet, bullets are separated from the body with two spaces

    Actually it's a bit more complicated, and depends on list-style properties. But in most cases WebKit uses a separation of 1 space plus 1/3 of the font ascent.

    Firefox, Chrome and Safari implement counter-style: disc with some sort of custom circle [...] Effectively, this means font-family isn't useful

    You can force the U+2022 character with list-style-type: "\2022 ". Firefox has supported it for a long time since version 39, and recently I have implemented it for Chromium 79 and WebKit.

    there seems to be relatively little appetite (for both the specification and implementations) to move forward

    Well, WebKit shipped a limited version of ::marker 2 years ago, more recently Firefox shipped it completely, in Chromium I have implemented the WebKit behavior behind a flag and I'm working on completing it. This allows marker customizations, and will be much more powerful when we start accepting more properties in it. So things are moving forward, though it's true that outside positioning is heavily underspecified.

  8. MatsPalmgren commented on Nov 10, 2019

    @MatsPalmgren
    * We should settle on some default value for `white-space` in markers (`pre`?) and assign it in UA origin.
    

    That seems reasonable to me, on the condition that the property works normally so that authors can override it as they see fit.

    * This default value may depend on whether the marker is inside or outside, e.g.
     [example snipped]
      But probably it's simpler to always have the same default value.
    

    Using the same value for both seems better to me.

    Fwiw, when I experimentally added ::marker { white-space:pre } in Gecko the test fallout was the expected.

  9. MatsPalmgren commented on Nov 10, 2019

    @MatsPalmgren

    Re. the marker alignment, you've already got https://drafts.csswg.org/css-lists-3/#marker-side which allows a little control. @MatsPalmgren, does this cover the case you had in mind?

    I was thinking of hypothetical marker positions where the marker's inline-axis end edge (and its trailing space) isn't adjacent to the principal box. (I'm not sure if that's possible with marker-side.)
    Anyway, if we allow authors to override the default white-space behavior then that's not really a problem.

  10. faceless2 commented on Nov 10, 2019

    @faceless2

    On re-reading my post I should clarify my observation on the relative lack of momentum on css-lists isn't a dig. The fact list bullets are largely as they were 20 years ago clearly means that end-users are not shouting about them the way they are over... well, over everything else I suppose. We've recently got it working, so from the perspective of a clean-room implementation the spec is noticeably thinner than much of the rest of CSS - that's the basis for my comment, no more.

    I'm fully aware of the effort required to specify this completely and now our W3C membership is complete, hope to pitch in on this over the next few months.

  11. MatsPalmgren commented on Nov 11, 2019

    @MatsPalmgren

    Here's my proposal for this issue:

    1. Add white-space as a property that applies to ::marker
    2. Add ::marker { white-space:pre } to the UA sheet
    3. Mention that an outside ::marker box has its display value blockified. (This makes it clear that if an author overrides white-space with say white-space:normal then any trailing space in an outside marker's text is expected to be truncated as it normally would at the line end in a block.)

    I think those changes would define how white-space should be handled unambiguously.
    I think we can punt on the other issues for now (multiline marker, allowing more properties etc).

  12. 12 remaining items

  13. faceless2 commented on Jan 9, 2020

    @faceless2

    I don't like pre-wrap as a default because it can wrap the marker into multiple lines when the content is long. And multiple lines is undefined for outside. At least with pre we can only have multiple lines if the author specifies a line break, and I don't think (many) people will do that.

    Adding text-space-collapse: preserve-spaces as well as white-space: pre would prevent long lines from wrapping, and disallow explicit newlines. https://www.w3.org/TR/css-text-4/#white-space-collapsing.

  14. fantasai commented on Jul 8, 2020

    @fantasai
    Collaborator

    @Loirooriol Mind reviewing? :) (Feel free to close and mark Commenter Satisfied if it looks good to you.)

  15. Loirooriol commented on Jul 8, 2020

    @Loirooriol
    ContributorAuthor

    @fantasai The change looks good, according to the resolution. But it's problematic for inside markers, #4891. So maybe there should be a note about the problem, or add text-space-trim: discard-after in the UA styles or something?

  16. fantasai commented on Jul 8, 2020

    @fantasai
    Collaborator

    @Loirooriol Done, thanks!

  17. Loirooriol commented on Jul 9, 2020

    @Loirooriol
    ContributorAuthor

    Thanks, looks great!

  18. added
    Commenter SatisfiedCommenter has indicated satisfaction with the resolution / edits.
    on Jul 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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