今天遇到一个bug,给了word-break:break-all
和width
,大部分文本都能正常换行,但是有一段标点符号很多的文本没有正常换行,查找了一些资料,做了一点测试,把踩坑过程记录下来。
测试数据如下图:
可以看到,默认只设置宽度的情况下:
1.连续的英文字符不会换行
2.连续的标点符号不会换行,并且连续的英文字母也不会换行,在中英文字符之间出现了换行
设置word-break: break-word
均能正常换行,但此处测试数据没有体现出word的概念,实际上如果是一个很长的单词卡在换行的位置,会出现某一行空白一大堆的情况,如下图:
此处由于dog.和后面的Anywhere没有空格分割,被当成一个长单词处理了,break-word的情况下不会将单词截断,因此会在单词前进行换行,导致上一行空白较多。
然而此处还有一个疑点,为什么一长串的标点符号能正常换行,dog.Anywhere这个会被认为是一整个单词,说明标点符号可以在单词之间出现,那么一串标点符号应该也能当作一个长单词才对。
个人猜测,由于英文单词本身就存在一些以连字符-
连接的单词,所以当一个标点符号出现在字母与字母之间时,浏览器会将前后合并为一个word处理,而单独一长串标点或者在字母之间出现过多标点时,每个标点会被当作一个word,因此break-word会在标点之后进行换行。
设置word-break: break-all
由于break-word
会存在单行空白过多的情况,大部分时候为了视觉美观会使用break-all
,这也是问题出现的前提。可以看到,在只设置宽度和break-all
的情况下,以一长串标点符号(中英文都会)作为句首的这两个元素没有按预期进行换行,标点符号冲破了宽度的限制。具体原因先按下不表,此处放一个能看出端倪的word-break:break-all
的例子如图:
可以看到,第二行应在dog的d和o之间换行,因此第二行能正常换行,但是第三行这个单字符就非常神奇了,符合直觉的第三行应该是og然后一堆标点符号(因为标点符号换行有问题),但是这里变成了一个单字符,被坑过的同学和聪明的同学应该猜到了问题所在,答案最后揭晓。
在word-break的基础上,增设white-space属性
可以看到,当增设white-space: pre
时,break-all
和break-word
都不能正常换行了。
MDN文档中对于此属性值的解释是:连续的空白符会被保留。仅在遇到换行符或<br/>元素时才会换行。
,而white-space的默认行为是连续的空白符会被合并,换行符当作空白符处理,根据填充盒子的需要来换行
,设置了pre之后相当于是显式要求遇到换行符或<br/>
元素才会换行。
如果设置white-space: pre-wrap
,对于以上的测试场景无明显影响,与仅设置word-break
行为一致,MDN文档中对于此属性值的解释是:连续的空白符会被保留。在遇到换行符或<br/>元素时,或根据填充盒子的需要来换行。
,相当于在默认行为上增加了对换行符的处理,对于当前无换行符的场景并无影响,也无法解决标点符号不换行的问题。
解决问题的关键钥匙:属性line-break
可以看到,添加了line-break: anywhere
之后,标点符号可以正常换行了。
MDN文档对这个属性的解释是设置CSS属性line-break可以用来处理如何断开带有标点符号的中日韩文本的行
。
实测下来发现这个属性其实对英文标点符号也生效,而且也不是只有带中日韩文本的才行,纯英文带长标点符号的也可以。因此个人对此属性的理解是用于处理如何断开带标点符号的行
。
答案揭晓
浏览器默认的line-break行为下(实测值非anywhere在此种情况下均为同等表现),有这样一段文本AAB。C
(其中标点符号可以换成任意中英文标点符号),假设此时行宽正好到B这个字符之后,即第一行可以完整显示AAB
,浏览器也不会在B字符之后换行,而是在第二个A字符后换行,保证换行之后行的开头不是标点符号,这就是引发问题的原因。
对于一长串标点符号来说,实际应换行的位置在其中两个标点符号之间,但因为换行后行首为标点符号,浏览器会尝试向前一个字符寻找换行点,但前一个字符又为标点符号,因此会继续向前寻找,直到找到第一个非标点符号的字符,把它作为下一行的行首进行换行。
因此上面例子中dog这个单词会被拆成三行,因为do之间可以break-all,但g作为一长串标点符号前的第一个字符,会被拿到下一行作为行首,所以o就单独出来了一行。
总结:line-break
默认行为及其他值非anywhere的情况下,换行点不能是标点符号前,而line-break: anywhere
则是将换行点设置为任意位置(包括标点符号前),于是就能达成预期中的正常换行行为。
至此,完结撒花🎉🎉🎉🎉🎉🎉🎉🎉。
(果然CSS才是前端三件套里最难的一个,太坑了)
参考资料
word-break - CSS:层叠样式表 | MDN (mozilla.org)