zoukankan      html  css  js  c++  java
  • word wrap 解惑

    源起

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

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

    长单词溢出

    长单词溢出

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

    长单词被强行断行

    长单词被强行断行

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

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

    规则

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

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

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

    在文字的呈现规则上,两者很不相同,CJK 文字中,一个字母就是一个字素(单词),独立成义,!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%28VS.85%29.aspx

    得出的结论如下:

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

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

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

    • white-space 是 white-space-collapsing 和 text-wrap 的缩写

    属性
    设置 white-space-collapsing
    设置 text-wrap
    空行
    空格
    文字自动换行
    效果

    normal
    collapse
    normal
    collapse
    collapse
    wrap
    忽略多余空行和空格,文字自动换行

    pre
    preserve
    none
    preserve
    preserve
    no wrap
    保留所有空行和空白,文字不自动换行

    nowrap
    collapse
    none
    collapse
    collapse
    no wrap
    忽略多余空行和空格,文字不自动换行

    pre-wrap
    preserve
    normal
    preserve
    preserve
    wrap
    保留所有空行和空白,文字自动换行

    pre-line
    preserve-breaks
    normal
    preserve
    collapse
    wrap
    合并多余空格,保留多余空行,文字自动换行

    • text-wrap 定义文本的自动换行效果

    属性
    效果

    normal
    在允许的断点处自动换行

    none
    文本不会自动换行;对于不“合身”的容器,文本将会溢出

    unrestricted
    在任意的文法单词间都可断行,比 normal 的限制要松散很多

    suppress
    除非断行处没有其他任何允许的断点,方可进行断行,这比 unrestricted 严格,比 normal 松散

    • word-wrap 执行最激进的单词断行控制,从单词的内部断开以防止文本溢出容器并且完全适应容器的宽度
    • 在 IE 的实际效果中,word-break 的效果要激进得多,它穷凶极恶地断开所有单词(如果到达边界的话)

    属性
    效果

    normal
    仅在允许的文本断点处自动换行

    break-word
    如果一行中没有其他可接受的断点,那么将强行断开文本单词

    • line-break 是断行的规则,针对东亚文字
    • 基本是针对日文的换行规则
    • word-break 是断行的规则,针对非东亚文字

    属性
    效果

    normal
    根据特定非东亚文字自己的规则来决定是否自动断行

    break-all
    允许非东亚语言文本行的任意字内断开。该值适合包含一些非东亚文本的东亚文本

    keep-all
    不允许非东亚语言文本行的任意字内断开。该值适合包含一些东亚文本的非东亚文本

    hyphenation
    文本会在合适的连字符处断开,这需要浏览器的支持

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

    word-wrap

    word-wrap

    word-break

    word-break

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

    兼容性

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

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

    解惑二三

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

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

    IE67 中浮动盒子杯具

    IE67 中浮动盒子杯具

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

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

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

    实践方案

    • 对于我们输出的内容(可控的),不使用任何 word-wrap 和 word-break 等属性,对于可能产生的长单词溢出这种小概率事件,首先考虑容器宽度是否合理,其次可以为长单词添加连字符“-”以便合理地断开,最后设置 overflow: hidden; 避免视觉上的溢出。
    • 对于用户输出的内容(不可控的),比如评论等,由于不排除用户会输入“dddddddddddd”这样没营养的垃圾数据,使用 word-wrap: break-word; 来强行截断。

    最后的观点

    • 不能完全迁就测试用例,因为有时不合现实情理。
    • 浏览器默认已经做得够好,强加诸如 break-all; 这样的指令是不优雅的。
    • 问题大多不在于实现,而在于设计(如容器太窄)。
    • 对于 bug 浏览器使用 hack 即可,这是它们的错。

    相关资源

    form:http://ued.taobao.com/blog/2010/10/14/research-of-word-wrap/

    物流配货网http://wlphw.com/ QQ在线:471226865点击这里给我发消息

  • 相关阅读:
    取得窗口大小和窗口位置兼容所有浏览器的js代码
    一个简单易用的导出Excel类
    如何快速启动chrome插件
    网页表单设计案例
    Ubuntu下的打包解包
    The source file is different from when the module was built. Would you like the debugger to use it anyway?
    FFisher分布
    kalman filter
    Group delay Matlab simulate
    24位位图格式解析
  • 原文地址:https://www.cnblogs.com/suizhikuo/p/2585305.html
Copyright © 2011-2022 走看看