Re: [css-text] pre-wrap and white space processing

Hi,

We discussed this white-space:pre-wrap topic on a recent teleconf, but failed to reach a good conclusion. One reason was that I tried to make an analogy with text editors and word processors, but there's so much variation there that this was counter productive.

An other reason was that we got confused at what the various behaviors were, and after further investigation, it turns out that they are not exactly what I thought they were (but they're still not interoperable).

Finally, Rossen and Smfr said they weren't too interested in changing what they currently have. However, what we currently have in IE vs Firefox vs Safari and Chrome isn't interoperable, so preserving the status quo would be unfortunate.

So Let's try again.

Note that word-wrap is also known by its better and newer name overflow-wrap, but to reduce context-switching mental overhead between this mail and writing tests/experiments, I'll use the old name in this mail since the new name isn't supported everywhere yet.

=== TL;DR
1) IE/Chrome/Safari wrap the same way, but don't collapse spaces the same way. Firefox and IE handle space collapsing the same way (don't collapse), but wrap differently.

2) Firefox seems to have a spec violation on word-break:break-all which other browsers don't have, but which results in a nice behavior.

3) The definition of word-wrap:break-word is ambiguous, and IE understands it differently in regular elements vs in a textarea, with one approach matching what firefox does and the other not (and we can't know about Chrome/Safari due to their different space collapsing behavior).

4) All these things interact, resulting in no interop, with various browsers exposing different useful behaviors in different case, but no browser having all the useful behaviors.

5) I have a suggestion (last section in this mail)


=== Details of browser behaviors.
Let's look at what happens with the following two strings:
"Hello    World             Bye"
"Hello    Universe             Bye"
and styling them with white-space:pre-wrap (representing preserved white space with _ and the limits of the content area with |)

==== Firefox (36) will do this:

|Hello____      |
|World__________|___
|Bye            |

|Hello____      |
|Universe_______|______
|Bye            |

The reason why Firefox wraps where it does is that it treat these spaces as  s, as prescribed in http://dev.w3.org/csswg/css-text-3/#white-space-phase-1

The wrapping is in my opinion not ideal, at least in the first example this there was room to fit "word" on the first line, but this behavior is fairly unsurprising when editing and adding spaces at the end of a line (either in a textarea or with contenteditable).

If you apply word-wrap: break-word, you get the following, which does not seem very nice to me, and which may or may not be spec compliant, as the spec does allows breaks in "words" but does not define what a "word" is and whether that includes  s:

|Hello____      |
|World__________|
|___Bye         |

|Hello____      |
|Universe_______|
|______Bye      |


If you apply word-break:break-all, you get the following, which while nice, is probably not spec compliant in the first case, as break-all only allows additional breaks between typographic letter units, and   isn't one.

|Hello____World_|
|____________Bye|

|Hello____Univer|
|se_____________|
|Bye            |

Once you account for the value of the word-wrap and overflow properties, the behavior in textareas is identical to divs.

==== IE (11) will do this
|Hello____World_|____________
|Bye            |

|Hello____      |
|Universe_______|______
|Bye            |

The first is nicer IMHO than firefox, but I cannot find a justification for it in the spec. The second one is the same as Firefox. This behavior is unsurprising when editing and adding spaces at the end of the line (that's a good thing).

If you apply word-wrap: break-word, nothing changes, which is not helpful, and may or may not be spec compliant since the spec is ambiguous as described above. IE takes the opposite interpretation from Firefox.

If you apply word-break:break-all, the first one stays unchanged, and the second one becomes the same as firefox, both of which seem expected given the definition of word-break:

|Hello____World_|____________
|Bye            |

|Hello____Univer|
|se_____________|
|Bye            |

The behavior in textareas (having neutralized the scrollbars using overflow:auto or overflow:hidden) is slightly different: when both word-wrap and word-break are normal, or when word-wrap is normal and word-break is break-all, the behavior is the same as with divs.

However, with word-wrap:break-word you get the same as firefox, suggesting that here IE took the other interpretation of whether word-wrap:break-word applies to spaces or not.
|Hello____      |
|World__________|
|___Bye         |

|Hello____      |
|Universe_______|
|______Bye      |

With both word-wrap:break-word and word-break:break-all, you get this, which doesn't seem desirable to me in the first example, and which I am not sure I can explain:

|Hello____Worl  |
|d_____________B|
|ye             |

|Hello____Univer|
|se_____________|
|Bye            |


==== Chrome (41) and Safari (8) will do this:
|Hello____World_|
|Bye            |

|Hello____      |
|Universe_______|
|Bye            |

The reason why they behave this way because point 4 of http://dev.w3.org/csswg/css-text-3/#white-space-phase-2 allows the UA to visually collapse advance widths of preserved tabs and white space characters at the end of the line.

Other than the lack of spaces overflowing, this is the same behavior as IE, which I think is nice. However, note that when editing and adding more spaces at the end of the line, the user has no indication of how many spaces they've added, or what the position of their insertion caret is in the run of spaces, which is confusing.

If you apply word-wrap: break-word, nothing changes, which is not helpful, but is easily explained by the fact that the spaces that would extend beyond the end of the line have been collapsed.

If you apply word-break:break-all, the first one stays unchanged, and the second one wraps the word. This is in my mind a good behavior, and seem expected given the definition of word-break:

|Hello____World_|
|Bye            |

|Hello____Univer|
|se_____________|
|Bye            |

The behavior in textareas is identical to regular elements.

=== Recommendation

Here's what I think we should do.

1) Align all browsers on a single behavior for white-space:pre-wrap (with both word-break and word-wrap being normal). I have personal opinions about which behavior would be best, but this is secondary to having UA vendors agree on something.

My order of preference would be:
a - Do as IE
b - Do as chrome and safari, possibly with an added provision to make editing less strange
c - Do this (preserve *and* wrap spaces):
|Hello____World_|
|____________Bye|

|Hello____      |
|Universe_______|
|______Bye      |

d - Do as firefox

2) Assuming we agree that with word-break:break-all wrapping *does not* occur in the middle of preserved spaces (and fix firefox accordingly), and depending on what we pick at point 1, the behavior of "white-space:pre-wrap; word-break:break-all" becomes one of the following 

Option a (IE):
|Hello____World_|____________
|Bye            |

|Hello____Univer|
|se_____________|
|Bye            |

Option b (Chrome/Safari):
|Hello____World_|
|Bye            |

|Hello____Univer|
|se_____________|
|Bye            |

Option c:
|Hello____World_|
|____________Bye|

|Hello____Univer|
|se_____________|
|Bye            |

Option d (fixed Firefox):
|Hello____      |
|World__________|___
|Bye            |

|Hello____Univer|
|se_____________|
|Bye            |


3) Clarify that with word-wrap:break-word wrapping *does* occur in the middle of preserved spaces, with no difference in behavior between regular elements and textareas. Also disallow the collapsing of trailing spaces that chrome and safari do when word-wrap is not 'normal'. Resulting in this behavior for "white-space:pre-wrap; word-wrap:break-word":

|Hello____World_|
|____________Bye|

|Hello____Univer|
|se_____________|
|Bye            |


4) If it wasn't picked as the base behavior in question 1, make behavior c available either trough a new value of the white-space property (pre-wrap-all?) or a new value of word-wrap (break-spaces? this name sounds reasonable with when we use the newer overflow-wrap name for this property)

|Hello____World_|
|____________Bye|

|Hello____      |
|Universe_______|
|______Bye      |

On the first example, this ends up being the same as "white-space: pre-wrap; word-break:break-all", but for the second it does not, as I only allow wrapping the spaces, in words the words.


I'll note that being able to get either three or four and hopefully both is the most important point for me and Bloomberg, and is what prompted me to look into this in the first place.

Best regards,
Florian

Received on Saturday, 21 March 2015 13:07:48 UTC