word-wrap 解惑

dddd

源起

我们经常需要“修复”一个老生常谈的“bug”,那就是文本的自动换行问题。在专业术语上,这种期望得到的渲染现象被称作“word wrap”,即文本处理器有能力把超出页边的整个词自动传到下一行。

在现实项目中,尤其是在测试阶段,鉴于测试使用非常极端的测试用例,我们经常需要“修复”如图所示的这个问题:

word-wrap 解惑
长单词溢出

图中,极长的这个英文单词(虽然是生造的)为了保证完整的显示,无奈地超出了容器的限制,它溢出了。为了“修复”这个“问题”,使得无论东亚还是西欧文字都能被限定在容器的尺寸范围内,我们一般会加上诸如“word-wrap: break-word; word-break: break-all”这样的属性,令我们满意(好吧,其实是令测试满意)的结果如图所示:

word-wrap 解惑
长单词被强行断行

从以结果现象为导向的观点出发,这个“bug”被“修复”了,但是在做了三五次这样的重复工作后,我开始产生这样几个疑问:

  1. word-wrap 和 word-break 究竟是什么?
  2. 为什么会乐此不疲地重复碰到这个问题?
  3. 这个问题是问题么?

规则

在解惑之前,有几个关乎问题本质的客观现实需要指出,因为这些“常识”最容易被人忽视:

CJK 文字和 !CJK 文字有各自的排版规则。

在这里,CJK 代表 Chinese, Japanese, and Korean,即东亚文字,!CJK 就是非东亚文字,大多数情况下是西欧文字。

在文字的呈现规则上,两者很不相同,CJK 文字中,一个字母就是一个字素(单词),独立成义,!CJK 文字中,一些字母组成一个字素,并且字素们由连接符“-”连接,或由空格“ ”分隔。

解惑一

word-wrap 和 word-break 究竟是什么?对于这个问题,直接拜访 W3C 官方,找到 CSS3 草案:http://www.w3.org/TR/2010/WD-css3-text-20101005/,再访问微软,借鉴诸如 http://msdn.microsoft.com/en-us/library/ms531184(VS.85).aspx.aspx)

得出的结论如下:

word-wrap, line-break, word-break 这几个属性都是 MS 的独立实现,随后其他浏览器也不同程度地实现了其中的某些,之后,这几个属性都被吸纳为 CSS3 标准。在对文字排版的渲染上,微软还是走在前面的。

在现有的 CSS3 草案中,关乎到文字排版的几个重要属性有:white-space,text-wrap,word-wrap,line-break,word-break。

根据 CSS3 的描述,列出这些属性各自的要点,这部分读者可以跳过……

word-wrap 解惑

做一个归纳:专门用于控制文本自动换行功能的属性是 text-wrap 和 word-wrap,而 line-break 和 word-break 用来控制断行和单词边界分隔,根据 W3C 的描述来说,word-wrap 是最激进的自动换行方式,可以强行断开单词。而现实情况是,word-break: break-all 的方式要更为激进,如图:

word-wrap 解惑
word-wrap

word-wrap 解惑
word-break

对比 word-wrap: break-word 和 word-break: break-all,两者都将文本限定在了容器的范围内,只是 break-all 将所有单词,不论长短地,通通截断,break-word 则非如此,它尽量地遵从了排版规则。

兼容性

由于几个属性都来自于微软(部分来自于 CSS3),那么理所当然 IE 是支持最良好的,不过对于浮动元素,IE 6/7 的表现会有些 bug(可在文后给出的 demo 中验证)。

至于其他浏览器,FF 3.6 不支持 word-break;Chrome 7 支持良好;Safari 5 同 Chrome;Opera 10 同 FF

解惑二三

碰到相关问题的场景大体是两个:

  1. 测试使用了很极端的测试用例(比如 asdfasdfasdfasdfasdfasdfasdf)
  2. IE 6/7 下,在宽度不大的容器中使用了浮动元素,同时浮动元素内包含了长的串,如图:

    word-wrap 解惑
    IE 6/7 中浮动盒子杯具

对于场景一,使用 word-wrap: break-word。

对于场景二,使用 IE 6/7 的 hack,word-break: keep-all 或者用 inline-block 来代替浮动(IE 6/7 中,hasLayout 的 inline 盒子大体等同于 inline-block)。

回头看疑问二,我们为什么会乐此不疲地重复碰到这个问题?原则上,各个浏览器默认的文字排版方式已经很好地顾及了 CJK 文字和 !CJK 文字,根据各个语言自己的规则来呈现排版,不应该出现诡异的问题。所以,对于上面的两个问题场景,之所以产生场景一,是因为使用了极端的测试用例,但是在现实中,这种极长的英文单词是根本不存在的(特殊行业除外),又,即使英文单词较长,也不应该突兀地截断,这有违西欧文字的排版规则。所以我认为,如果在现实环境下发生场景一中的问题,责任应该在于版面的设计,比如容器宽度太小,而不是去截断文本;对于场景二,应该归咎于 IE 6/7 的渲染 bug,这时,使用 inline-block 代替,或用 word-break: keep-all 来给犯错的浏览器擦屁股。

实践方案

最后的观点

相关资源

题图:https://unsplash.com/photos/FKqH1QhUqaw By @Julian Santa Ana