<div>设置宽度,汉字正常换行,输入字母/数字不换行的解决方案分析
2012-12-11 18:35
501 查看
我们经常需要“修复”一个老生常谈的“bug”,那就是文本的自动换行问题。在专业术语上,这种期望得到的渲染现象被称作“wordwrap”,即文本处理器有能力把超出页边的整个词自动传到下一行。
在现实项目中,尤其是在测试阶段,鉴于测试使用非常极端的测试用例,我们经常需要“修复”如图所示的这个问题:
![](http://img04.taobaocdn.com/tps/i4/T1KTFNXm4zXXXXXXXX-420-113.jpg)
长单词溢出
图中,极长的这个英文单词(虽然是生造的)为了保证完整的显示,无奈地超出了容器的限制,它溢出了。为了“修复”这个“问题”,使得无论东亚还是西欧文字都能被限定在容器的尺寸范围内,我们一般会加上诸如
word-wrap:break-word;
word-break:break-all;
这样的属性,令我们满意(好吧,其实是令测试满意)的结果如图所示:
![](http://img03.taobaocdn.com/tps/i3/T1CTdNXmhzXXXXXXXX-107-194.jpg)
长单词被强行断行
从以结果现象为导向的观点出发,这个“bug”被“修复”了,但是在做了三五次这样的重复工作后,我开始产生这样几个疑问:
word-wrap和word-break究竟是什么?
为什么会乐此不疲地重复碰到这个问题?
这个问题是问题么?
CJK文字和!CJK文字有各自的排版规则。
在这里,CJK代表Chinese,Japanese,andKorean,即东亚文字,!CJK就是非东亚文字,大多数情况下是西欧文字。
在文字的呈现规则上,两者很不相同,CJK文字中,一个字母就是一个字素(单词),独立成义,!CJK文字中,一些字母组成一个字素,并且字素们由连接符“-”连接,或由空格“”分隔。
有关CJK文字更多的排版规则上,比较有代表性的是:对中文来说,标点符号不能成为行首(特殊除外);双字长的标点符号(省略号、破折号)不能断开。
对于!CJK,主要是:单词不能在中间不合法地断开(合法情况例如从连接符处断开);标点符号不能成为行首(特殊除外)
得出的结论如下:
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的缩写
text-wrap定义文本的自动换行效果
word-wrap执行最激进的单词断行控制,从单词的内部断开以防止文本溢出容器并且完全适应容器的宽度
在IE的实际效果中,word-break的效果要激进得多,它穷凶极恶地断开所有单词(如果到达边界的话)
line-break是断行的规则,针对东亚文字
基本是针对日文的换行规则
word-break是断行的规则,针对非东亚文字
做一个归纳:专门用于控制文本自动换行功能的属性是text-wrap和word-wrap,而line-break和word-break用来控制断行和单词边界分隔,根据W3C的描述来说,word-wrap是最激进的自动换行方式,可以强行断开单词。而现实情况是,word-break:break-all;的方式要更为激进,如图:
![](http://img01.taobaocdn.com/tps/i1/T1LDFNXmRzXXXXXXXX-108-355.jpg)
word-wrap
![](http://img04.taobaocdn.com/tps/i4/T1aDJNXchzXXXXXXXX-112-325.jpg)
word-break
对比word-wrap:break-word;和word-break:break-all;,两者都将文本限定在了容器的范围内,只是break-all将所有单词,不论长短地,通通截断,break-word则非如此,它尽量地遵从了排版规则。
至于其他浏览器,FF3.6不支持word-break;Chrome7支持良好;Safari5同Chrome;Opera10同FF
测试使用了很极端的测试用例(比如asdfasdfasdfasdfasdfasdfasdf)
IE67下,在宽度不大的容器中使用了浮动元素,同时浮动元素内包含了长的串,如图:
![](http://img02.taobaocdn.com/tps/i2/T1WnFNXiVzXXXXXXXX-569-290.jpg)
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;来给犯错的浏览器擦屁股。
对于用户输出的内容(不可控的),比如评论等,由于不排除用户会输入“dddddddddddd”这样没营养的垃圾数据,使用word-wrap:break-word;来强行截断。
浏览器默认已经做得够好,强加诸如break-all;这样的指令是不优雅的。
问题大多不在于实现,而在于设计(如容器太窄)。
对于bug浏览器使用hack即可,这是它们的错。
demo页面:http://ued.taobao.com/lab/word-wrap/word-wrap.html
转自淘宝UED
在现实项目中,尤其是在测试阶段,鉴于测试使用非常极端的测试用例,我们经常需要“修复”如图所示的这个问题:
![](http://img04.taobaocdn.com/tps/i4/T1KTFNXm4zXXXXXXXX-420-113.jpg)
长单词溢出
图中,极长的这个英文单词(虽然是生造的)为了保证完整的显示,无奈地超出了容器的限制,它溢出了。为了“修复”这个“问题”,使得无论东亚还是西欧文字都能被限定在容器的尺寸范围内,我们一般会加上诸如
word-wrap:break-word;
word-break:break-all;
这样的属性,令我们满意(好吧,其实是令测试满意)的结果如图所示:
![](http://img03.taobaocdn.com/tps/i3/T1CTdNXmhzXXXXXXXX-107-194.jpg)
长单词被强行断行
从以结果现象为导向的观点出发,这个“bug”被“修复”了,但是在做了三五次这样的重复工作后,我开始产生这样几个疑问:
word-wrap和word-break究竟是什么?
为什么会乐此不疲地重复碰到这个问题?
这个问题是问题么?
规则
在解惑之前,有几个关乎问题本质的客观现实需要指出,因为这些“常识”最容易被人忽视:CJK文字和!CJK文字有各自的排版规则。
在这里,CJK代表Chinese,Japanese,andKorean,即东亚文字,!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 | nowrap | 保留所有空行和空白,文字不自动换行 |
nowrap | collapse | none | collapse | collapse | nowrap | 忽略多余空行和空格,文字不自动换行 |
pre-wrap | preserve | normal | preserve | preserve | wrap | 保留所有空行和空白,文字自动换行 |
pre-line | preserve-breaks | normal | preserve | collapse | wrap | 合并多余空格,保留多余空行,文字自动换行 |
属性 | 效果 |
normal | 在允许的断点处自动换行 |
none | 文本不会自动换行;对于不“合身”的容器,文本将会溢出 |
unrestricted | 在任意的文法单词间都可断行,比normal的限制要松散很多 |
suppress | 除非断行处没有其他任何允许的断点,方可进行断行,这比unrestricted严格,比normal松散 |
在IE的实际效果中,word-break的效果要激进得多,它穷凶极恶地断开所有单词(如果到达边界的话)
属性 | 效果 |
normal | 仅在允许的文本断点处自动换行 |
break-word | 如果一行中没有其他可接受的断点,那么将强行断开文本单词 |
基本是针对日文的换行规则
word-break是断行的规则,针对非东亚文字
属性 | 效果 |
normal | 根据特定非东亚文字自己的规则来决定是否自动断行 |
break-all | 允许非东亚语言文本行的任意字内断开。该值适合包含一些非东亚文本的东亚文本 |
keep-all | 不允许非东亚语言文本行的任意字内断开。该值适合包含一些东亚文本的非东亚文本 |
hyphenation | 文本会在合适的连字符处断开,这需要浏览器的支持 |
![](http://img01.taobaocdn.com/tps/i1/T1LDFNXmRzXXXXXXXX-108-355.jpg)
word-wrap
![](http://img04.taobaocdn.com/tps/i4/T1aDJNXchzXXXXXXXX-112-325.jpg)
word-break
对比word-wrap:break-word;和word-break:break-all;,两者都将文本限定在了容器的范围内,只是break-all将所有单词,不论长短地,通通截断,break-word则非如此,它尽量地遵从了排版规则。
兼容性
由于几个属性都来自于微软(部分来自于CSS3),那么理所当然IE是支持最良好的,不过对于浮动元素,IE67的表现会有些bug(可在文后给出的demo中验证)。至于其他浏览器,FF3.6不支持word-break;Chrome7支持良好;Safari5同Chrome;Opera10同FF
解惑二三
碰到相关问题的场景大体是两个:测试使用了很极端的测试用例(比如asdfasdfasdfasdfasdfasdfasdf)
IE67下,在宽度不大的容器中使用了浮动元素,同时浮动元素内包含了长的串,如图:
![](http://img02.taobaocdn.com/tps/i2/T1WnFNXiVzXXXXXXXX-569-290.jpg)
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即可,这是它们的错。
相关资源
CSS3草案:http://www.w3.org/TR/2010/WD-css3-text-20101005/demo页面:http://ued.taobao.com/lab/word-wrap/word-wrap.html
转自淘宝UED
相关文章推荐
- <div>设置宽度,汉字正常换行,输入字母/数字不换行的解决方案分析
- <td> 设置了 style="width:100px;" 不起作用;div 内容溢出不换行 解决方案
- <span> 无法设置宽度的完美解决方案!
- js验证输入字段是否含有字母数字function checkChar(ic) { if (ic >= 48 && ic <= 57) { return 1; } if ((i
- 开发日志:设置<DIV>内容不自动换行,及inline后width和height等失效的问题
- Android editview 设置只能输入数字、字母和汉字
- 为table中的td设置过宽度后,只对汉字有效,对非汉字(英文字母、数字、字符)无效
- jsp不解析换行\n,textarea输入换行符后应该是'\n',在div中展示时替换成'<br>'
- 关于服务端访问报错后直接跳转到错误页而不显示返回信息问题即 <customErrors> 标记的“mode”属性设置为“Off”的问题的解决方案
- "<item> tag requires a 'drawable' attribute"-selector设置颜色不成功-解决方案
- 用正则表达式限制文本框只能输入数字,小数点,英文字母,汉字等各类代码
- 第九周OJ总结<1>-统计出其中英文字母、数字、空格和其他字符的个数
- text-overflow使用文字超多div的宽度或超过在table中<td>
- actionscript3.0显示输入数字,字母,汉字
- asp.net 限制textbox只能输入数字,并且防止启用输入法来输入字母或汉字
- 用正则表达式限制文本框只能输入数字,小数点,英文字母,汉字等
- [转]用正则表达式限制文本框只能输入数字,小数点,英文字母,汉字等各类代码
- ACM457现在给出了一个只包含大小写字母的字符串,不含空格和换行,要求把其中的大写换成小写,小写换成大写,然后输出互换后的字符串。输入 第一行只有一个整数m(m<=10),表示测试数据组数。
- Android代码设置EditText只输入数字、字母
- jsp页面如何控制单元格不区分汉字,字母,数字自动换行