[csswg-drafts] [css-text] A single leading white-space prevents word breaking honoring white-space: pre-wrap

javifernandez has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-text] A single leading white-space prevents word breaking honoring white-space: pre-wrap ==
Lets considering this simple test case:

```
<!DOCTYPE html>
<style>
div {
  font-family: Ahem;
  font-size: 20px;
  line-height: 1;
  white-space: pre-wrap;
  width: 2ch;
  border: 2px solid blue;
}
.ch1 {
  width: 1ch;
}
.break-all {
  word-break: break-all;
  border-color: red;
}
.break-word {
  word-wrap: break-word;
  border-color: orange;
}
.break-break-word {
  word-break: break-word;
  border-color: purple;
}
</style>
<div>  xx</div>
<div class="ch1"> xx</div>
<div class="break-word"> xx</div>
<div class="ch1 break-word"> xx</div>
<div class="break-break-word"> xx</div>
<div class="ch1 break-break-word"> xx</div>
<div class="break-all"> xx</div>
<div class="ch1 break-all"> xx</div>
```
The spec prose about the **pre-wrap** value is clear in this case: 

https://drafts.csswg.org/css-text-3/#white-space-phase-1
> If white-space is set to pre or pre-wrap, any sequence of spaces is treated as a sequence of non-breaking spaces. However, a soft wrap opportunity exists at the end of the sequence. 

So, we got, as expected, the same result in all lf the major browsers:

<table>
<tr><td colspan="5">Case 1.1: &lt;div>  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42541255-ecc44e0e-84a1-11e8-8490-c8765036499f.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541255-ecc44e0e-84a1-11e8-8490-c8765036499f.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541255-ecc44e0e-84a1-11e8-8490-c8765036499f.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541255-ecc44e0e-84a1-11e8-8490-c8765036499f.png"/></td></tr>
<tr><td colspan="5">Case 1.2: &lt;div class="ch1">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42541972-f0fb3eb2-84a4-11e8-9727-dcfba94e7740.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541972-f0fb3eb2-84a4-11e8-9727-dcfba94e7740.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541972-f0fb3eb2-84a4-11e8-9727-dcfba94e7740.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541972-f0fb3eb2-84a4-11e8-9727-dcfba94e7740.png"/></td></tr>
</table>

If we use the **word-wrap: break-word** in combination with the _pre-wrap_, we introduce additional breaking opportunities to avoid the overflow:

<table>
<tr><td colspan="5">Case 2.1: &lt;div class="break-word">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42564082-1a4e23e6-8500-11e8-9a6f-2905e24fa787.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42564083-1a6d2174-8500-11e8-9a45-eff2254498ad.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42564083-1a6d2174-8500-11e8-9a45-eff2254498ad.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42564083-1a6d2174-8500-11e8-9a45-eff2254498ad.png"/></td></tr>
<tr><td colspan="5">Case 2.2: &lt;div class="ch1 break-word">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42565064-ae196ae8-8502-11e8-9e88-cfde8b13ae24.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42565064-ae196ae8-8502-11e8-9e88-cfde8b13ae24.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42565064-ae196ae8-8502-11e8-9e88-cfde8b13ae24.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42565064-ae196ae8-8502-11e8-9e88-cfde8b13ae24.png"/></td></tr>
</table>
 
Chrome diverges from the behavior the rest of the browsers follow in the case 2.1. I think it's a clear bug, since the leading _white-space_ is an actual breaking opportunity that avoids the overflow, hence, no need to apply the _word-wrap_ property in this case, which will imply breaking the word. In the case 2.2, though, all the browsers are interoperable and there is no way to avoid breaking the word. I'd like to remark that all of them apply the _pre-wrap_ value and breaks in the leading white-space. 

I think there are no doubts, so far, but lets consider now what would happen if we use the **work-break** property instead of the _word-wrap_. As far as I understand, the _word-wrap_ property is applied **after** considering all the breaking opportunities, and only in the case that the word still overflows, we can apply the additional line-breaking opportunities, depending on the specific value of the _word-wrap_ property.

However, in the case of the _word-break_ property, the new breaking opportunities must be evaluated at the same time than the ones provided by the white-space property. Lets consider now the case of **word-break: break-word**; this is how each browser behaves in this case:

<table>
<tr><td colspan="5">Case 3.1: &lt;div class="break-break-word">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42566889-563c2be8-8508-11e8-961a-cfb7efa1e4b7.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42566888-561aae6e-8508-11e8-931d-f3a01a778476.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42566888-561aae6e-8508-11e8-931d-f3a01a778476.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42566888-561aae6e-8508-11e8-931d-f3a01a778476.png"/></td></tr>
<tr><td colspan="5">Case 3.2: &lt;div class="ch1 break-break-word">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42567870-8221b0d6-850b-11e8-8c13-862f60bd99c0.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42567871-823accf6-850b-11e8-91de-b8c136f65c22.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42567870-8221b0d6-850b-11e8-8c13-862f60bd99c0.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42567871-823accf6-850b-11e8-91de-b8c136f65c22.png"/></td></tr>
</table>

Chrome also diverges in Case 3.1 from the rest of the browsers; however, **Firefox and Edge don't implement the break-word** value, since it was removed in the last draft of the CSS Text spec. Hence, the comparison is only valid with Safari, which I think implements the right behavior. As it was commented in Case 2.1, the word shouldn't be broken if there are other breaking opportunities before, in this case, the leading _white-space_. This is also the default behavior applied by Firefox and Edge since they parse the _break-word_ as invalid.

Finally, lets evaluate what happens if we use **word-break: break-all** value, which is still defined in the last draft of the spec and indeed implemented by all the browsers:

<table>
<tr><td colspan="5">Case 4.1: &lt;div class="break-all">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42568895-ec0b7a06-850e-11e8-9507-67ce36f6276b.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42568895-ec0b7a06-850e-11e8-9507-67ce36f6276b.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42568896-ec2eca88-850e-11e8-9ea8-ad87fbf21e80.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42568895-ec0b7a06-850e-11e8-9507-67ce36f6276b.png"/></td></tr>
<tr><td colspan="5">Case 4.2: &lt;div class="ch1 break-all">  xx&lt;/div></td></tr>
<tr><td>Chorme</td><td>Firefox</td><td>Safari</td><td>Edge</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42569274-495c1f8e-8510-11e8-9e44-ce2e988ea840.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42569275-497cfc54-8510-11e8-920e-749b40c25349.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42569275-497cfc54-8510-11e8-920e-749b40c25349.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42569275-497cfc54-8510-11e8-920e-749b40c25349.png"/></td></tr>
</table>

Only Safari shows a different behavior in Case 4.1, which uses the leading white-spaces as priority breaking opportunity, so it doesn't need to break the word. As it was commented before, I think this is the correct and most coherent behavior; I don't see why we need to break the word if it's not necessary. 

The case 4.2 is different, since even breaking at the leading white-space, there is no enough space for the word, hence, honoring the break-all value, the word is broken to avoid the overflow. Chrome is diverging in this case and it actually lead to overflow, which I think it's incorrect because it's perfectly avoidable.

The following table describes my proposal for each of the cases analyzed before:

<table>
<tr><td>Case 1.1</td><td>Case 1.2</td><td>Case 2.1</td><td>Case 2.2</td><td>Case 3.1</td><td>Case 3.2</td><td>Case 4.1</td><td>Case 4.2</td><tr>
<tr><td colspan="2" align="center">pre-wrap</td><td colspan="2" align="center">pre-wrap+word-wrap</td><td colspan="2" align="center">pre-wrap+break-word</td><td colspan="2" align="center">pre-wrap+break-all</td><tr>
<tr><td><img src="https://user-images.githubusercontent.com/2230241/42564082-1a4e23e6-8500-11e8-9a6f-2905e24fa787.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42541972-f0fb3eb2-84a4-11e8-9727-dcfba94e7740.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42564083-1a6d2174-8500-11e8-9a45-eff2254498ad.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42565064-ae196ae8-8502-11e8-9e88-cfde8b13ae24.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42566888-561aae6e-8508-11e8-931d-f3a01a778476.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42567870-8221b0d6-850b-11e8-8c13-862f60bd99c0.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42568896-ec2eca88-850e-11e8-9ea8-ad87fbf21e80.png"/></td>
<td><img src="https://user-images.githubusercontent.com/2230241/42569275-497cfc54-8510-11e8-920e-749b40c25349.png"/></td></tr>
</table>

My proposal matches Safaris's behavior in all the cases and it basically avoids to break the word in any case if there are other soft-breaking opportunities before.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/2907 using your GitHub account

Received on Wednesday, 11 July 2018 12:54:29 UTC