Skip to content

[css-text] Clarify whether soft breaks exist at boundaries of an inline element with word-break:break-all #3897

Closed

Description

@jfkthame

While looking into some Gecko bugs related to word-break, I'm trying to understand exactly where the break-all value should be allowing soft line break opportunities, and it's not clear to me that the spec text addresses some edge cases.[1]

Consider an example like <div>abc<span>xyz</span>def</div>, where the div has word-break:normal and the span has word-break:break-all.

It's clear that break opportunities exist between 'x' and 'y', and between 'y' and 'z'. But is there a break opportunity between 'c' and 'x'? Between 'z' and 'd'?

Existing browsers disagree on this: AFAICT, Webkit allows a break between 'c' and 'x', but not between 'z' and 'd', while Blink does not allow it in either of these positions. So if this div is reflowed with a width of 0, Safari will render it as

abc
x
y
zdef

while Chrome will render as

abcx
y
zdef

I can't tell from the spec which of these, if either, is correct; am I overlooking text somewhere that makes this clear, or is it unspecified?

Personally, I think the most intuitive result would be

abc
x
y
z
def

and would like to patch Gecko such that it would have this behavior - i.e. if the letter on either side of the boundary has word-break:break-all, then a break opportunity exists. If it's not currently clear in the spec, could we agree that this is the best result and converge on it?

[1] https://drafts.csswg.org/css-text-3/#word-break-property

Activity

  1. emilio commented on May 8, 2019

    @emilio
    Collaborator
  2. kojiishi commented on May 8, 2019

    @kojiishi
    Contributor

    I agree the spec can be improved more, but I guess this case is where the spec says the boundary should belong to the nearest common ancestor, in this case, div. @fantasai can you confirm?

  3. frivoal commented on May 9, 2019

    @frivoal
    Collaborator

    Yes, this is covered by the second sentence of the third bullet from the bottom in section 5.1:

    For soft wrap opportunities defined by the boundary between two characters, the properties on nearest common ancestor of the two characters controls breaking.

    So, in this case, as Koji says, at the boundary between c and x, and between z and d, the word-break:normal style of the div applies, and this rendering is correct:

    abcx
    y
    zdef
    

    As for making the spec clearer, if you have a concrete suggestion, I'm happy to take it, but as far as I can tell, the problem isn't that the sentence isn't clear, but rather that there are lots of rules, and that it is easy to fail to notice this one.

    WPT has some tests that relate to this, but it could use some more.

  4. self-assigned this
    on May 9, 2019
  5. jfkthame commented on May 9, 2019

    @jfkthame
    ContributorAuthor

    OK, I see. I recall this is how letter-spacing is defined to work across element boundaries, for example (though does anyone actually implement it that way?), but missed that the same idea applied to soft breaks.

    TBH, I think the result this gives will tend to be counter-intuitive for an author. Breakability is (to my mind) an attribute of the characters, so that in an example like

    data:text/html,<style>b,i{word-break:break-all}p{width:0}</style><p><b>hello</b><i>world</i>
    

    it's unexpected for the "o" and "w", both of which have the break-all attribute, to end up stuck together.

    Given that there isn't currently full interop in this area (this example renders with "ow" on the same line in Chrome, but in Safari each letter is on a separate line), is this something that we can/should reconsider?

    (The same would apply to letter-spacing, fwiw:

    data:text/html,<style>b,i{letter-spacing:1em}</style><p><b>hello</b><i>world</i>
    

    should, as I understand the spec, have no letter-spacing between "o" and "w", but Chrome, Safari and Firefox all have 1em of spacing there. Again, ISTM that the behavior called for by the spec, ignoring the letter-spacing of the inlines on both sides of the boundary and looking to the common ancestor, is not what an author would likely expect.)

  6. jfkthame commented on May 9, 2019

    @jfkthame
    ContributorAuthor

    Actually, on the surface it seems like this contradicts the spirit of #3886, where it was just resolved that "Inline box boundaries don't affect line breaking opportunities".

    Consider:

    data:text/html,<style>p{width:0}span{word-break:break-all}</style><p><span>foo</span><span>bar</span>
    

    vs:

    data:text/html,<style>p{width:0}span{word-break:break-all}</style><p><span>fo</span><span>ob</span><span>ar</span>
    

    The only difference between these is where the boundaries of the inlines fall; the actual styles applied to all the text is the same in both. Yet Chrome (following the spec text as pointed out above) renders them differently, with pairs of characters stuck together at the span boundaries. Safari, OTOH, and also latest Firefox Nightly (since the patch in https://bugzilla.mozilla.org/show_bug.cgi?id=1507744), renders both examples the same, with no letter pairs stuck together.

  7. kojiishi commented on May 9, 2019

    @kojiishi
    Contributor

    it seems like this contradicts the spirit of #3886

    I agree, I referred to the issue because I felt the same as you. I think we'll need to discuss that and make more edits.

  8. kojiishi commented on May 9, 2019

    @kojiishi
    Contributor

    TBH, I think...Breakability is (to my mind) an attribute of the characters

    I actually like the idea.

    letter-spacing is defined...does anyone actually implement it that way?

    I think last time @litherum said he can try it out, and we're waiting for the result.

  9. frivoal commented on May 9, 2019

    @frivoal
    Collaborator

    Actually, on the surface it seems like this contradicts the spirit of #3886

    I see where you're coming from, but I don't see it this way. #3886 is about making sure that an unstyled span (or a span styled in an irrelevant way) doesn't change anything. In the case you're describing, the spans are styled, so they are having an effect. Yes, there's two of them, and they are contiguous, but it is because they are styled in a way that affects line breaking that something happens, not just because we added spans to the markup.

    I think the result this gives will tend to be counter-intuitive [...]
    Given that there isn't currently full interop in this area [...], is this something that we can/should reconsider

    I don't find it counter intuitive, so I'd leave it as is, but yes, it does seem that the lack of interop makes it possible to reconsider if we want to.

    As for why I think it's fine: the primary purpose of break-word is to deal with east-asian typography. If we think about it in the abstract based on the abc<span>xyz</span>def example you gave, your proposal may seem sound, but that example isn't really a use case. If we look at actual use cases, I think it the current definition does the intuitive thing. Examples:

    1. turn off breaking in the middle of words but keep breaks between words for Japanese by applying word-break:keep-all to individually marked up words:
     p { word-break: break-all; } /* this line optional, defaults are fine*/
    .word { word-break: keep-all; }
     <p><span class=word>日本語を</span><span class=word>文節ごと</span><span class=word>分割する</span>
    1. similar to 1, but turn off middle-of-the-word breaks for a single word (for example, a name, a brand, etc) in the middle of otherwise break-all text
     p { word-break: break-all; } /* this line optional, defaults are fine*/
    .name { word-break: keep-all; }
     <p>我叫<span class=name>罗阳</span>。
    1. quoting some old-fashioned space-less text in modern space separated Korean:
    :lang(ko) { word-break: keep-all; }
    :lang(zh) { word-break: break-all; }
     <p lang=ko>훈민정음 첫 문장은 <q lang=zh>國之語音異乎中國</q> 입니다.

    Example 3 would work with the rule you proposed as well as the current one, but example 1 or 2 would not work with the rule you propose.

    All in all, I think it is a discussion worth having, but my preference would be no change (other than maybe editorial clarifications and additional examples).

  10. frivoal commented on May 9, 2019

    @frivoal
    Collaborator

    (also, can we leave letter spacing out of this? Even if there are similarities, it's a separate piece of spec text, driven by separate use cases. If you feel that's wrong too, please open a separate bug).

  11. jfkthame commented on May 9, 2019

    @jfkthame
    ContributorAuthor

    I'm not sure I follow your examples. In (1), no browser I tested (Chrome, Safari, Firefox) breaks between the words at all. In any case, this use-case can (better?) be addressed by inserting ZWSP at the desired word breaks, rather than per-word markup -- although if you particularly want to do it based on markup, without the break points being part of the text stream, you could do this by using .word::after { content: '\200b' } to introduce the breaks.

    Regarding (2), keeping the name unbroken, this seems to me like it should work exactly as an author would expect using the approach I suggest, although currently the keep-all here doesn't seem to work correctly in Firefox; this looks like a bug. In Chrome the two-character name also stays glued to the preceding character that was not part of the name. IMO this would be unexpected; applying the keep-all attribute to the two characters of the name (only) should ensure those characters stay together, but shouldn't affect the fact that there's a possible break before it.

  12. jfkthame commented on May 9, 2019

    @jfkthame
    ContributorAuthor

    My codepen showing that no browser currently splits between the words in (1), afaics: https://codepen.io/anon/pen/LoGWoq

    (And using word::after to introduce ZWSP works as expected in both Chrome and Firefox, but not Safari.)

  13. 21 remaining items

  14. faceless2 commented on Jan 21, 2020

    @faceless2
  15. removed their assignment
    on Dec 4, 2020
  16. frivoal commented on Dec 30, 2022

    @frivoal
    Collaborator

    Marked the existing tests as tentative, since they're interesting, but no longer have a basis in current spec text web-platform-tests/wpt#37700

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