曾几什么时候,display:inline-block 已经深刻「大街小巷」,随处可见 「display:inline-block; *display:inline; *zoom:1; 」这样的代码。现在现代浏览器已经全面支持这个属性值了,上面的代码只是为了兼容 IE六、7 而已。那么你真的了解 inline-block 了吗?本文将带你深刻剖析该属性值的前世此生,让你更好的理解和运用 inline-block。(本文约定 display:inline-block 简写为 inline-block)css
开篇咱们来看几个问题:html
也许有人问你为什么要写「 display:inline-block; *display:inline; *zoom:1; 」 来兼容 IE六、7 时,你会立马答道:由于 IE六、7 不支持 display:inline-block 呗!不知道什么时候起,惯性思惟给开发者带来了这样一个可怕的概念。万物都是辩证的,当你写下这些的时候,可曾怀疑过大众观点真的可靠吗?也许你认为这些无关 紧要,实现效果就好。可是若是不能理解每一个属性或属性值的根本,你将永远没法全面的了解它,人云亦云只会让你浅尝辄止,止步不前。那么这里就涉及到所谓的 「CSS 学习瓶颈」的问题了,这个问题张鑫旭《说说CSS 学习中的瓶颈》一文有详细阐述,虽然部分观点我不是很赞同,可是中心思想仍是很值得思考的。文中有几个不错的问题这里也列举出来供你们观摩:web
好了,回到 inline-block 的认知的问题,个人观点是:chrome
IE 从 5.5 开始就已经支持 display:inline-block 了,只是支持的并非那么完善。api
在 msdn 微软开发者社区,找到了 IE 从5.5 开始支持 inline-block 的证据:浏览器
The inline-block value is supported starting with Internet Explorer 5.5. You can use this value to give an object a layout without specifying the object’s height or width.app
这里明确指出:从 IE5.5 开始支持 inline-block。ide
连接:http://msdn.microsoft.com/zh-cn/library/ie/ms530751(v=vs.85).aspxwordpress
那么既然 IE5.5 开始就已经支持了 inline-block,为什么咱们还要写那么一坨 CSS 呢?同时咱们知道 IE六、7 中 display:inline-block 是能够触发 hasLayout 的,触发了 hasLayout 的元素表现出来的特征就是一个独立的矩形容器,能够设置宽高并且不受外部元素的影响,相似于现代浏览器中的 Block formatting contexts (块级格式化上下文)的概念。布局
下面来作一个详细的测试,分别看看 IE6 中 inline 元素和 block 元素的表现:
1)inline 元素 display:inline-block
IE6 中截图以下:
.dib-inline, .dib-block {
width:100px;
height:30px;
line-height:30px;
text-align:center;
}
.dib-inline {
display:inline-block;
}
测试代表:IE6 中 inline 元素只要触发了 hasLayout 其表现就相似于 inline-block,这里设置 display:inline-block; 或者 zoom:1; 等其余属性值能够触发 hasLayout ,表现出来是同样的。
查看 DEMO(2013-3-22更新)
2)block 元素 display:inline-block
IE6 中截图以下:
.dib-inline, .dib-block {
width:100px;
height:30px;
line-height:30px;
text-align:center;
}
.dib-block{
display:inline-block;
}
测试代表:IE6 中 block 元素即便触发了 hasLayout 也不能具备 inline-block 元素不换行的特性。想要 block 元素支持 inline-block 元素的特性,咱们能够这样作:
.dib-block {
display:inline;
zoom:1;
}
首先让 block 元素转化为 inline 元素,强制其不换行;而后经过 zoom:1 触发 hasLayout,使其能够设置宽高。修复后的 截图以下:
3)结合现代浏览器
综上,现代浏览器都支持 display:inline-block ,IE六、7 inline 元素也能够达到一样的效果,IE六、7 block 元素须要设置 display:inline; zoom:1; 它们结合在一块儿即是:
display:inline-block; /* 现代浏览器 +IE六、7 inline 元素 */
*display:inline; /* IE六、7 block 元素 */
*zoom:1;
为了避免让支持 CSS2.1 inline-block 的浏览器 重置为 inline,咱们针对 IE六、7 作一个 hack。因为现代浏览器也开始支持 zoom 属性,这里只是但愿 IE六、7 中生效,因此仍是 hack 一下比较合适。至此产生了咱们熟悉的兼容各个浏览器的 inline-block 写法。
小结:IE六、7 并非不支持 inline-block,只是 block 元素须要作一些处理来达到 inline-block 的效果。
说了不少,或许不少朋友还不是太明白到底什么是 inline-block?W3C 在 CSS2.1 The ‘display’ property 中描述以下:
This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
大体意思就是:inline-block 后的元素建立了一个行级的块容器,该元素内部(内容)被格式化成一个块元素,同时元素自己则被格式化成一个行内元素。
直白一点的意思就是:inline-block 的元素既具备 block 元素能够设置宽高的特性,同时又具备 inline 元素默认不换行的特性。固然不只仅是这些特性,好比 inline-block 元素也能够设置 vertical-align 属性。简而言之:
inline-block 后的元素就是一个格式化为行内元素的块容器( Block container )
怎么样?听起来还不错吧!
前面已经证实了 IE 5.5 开始就支持了 inline-block,那么 IE5.5 是何时发布的呢?话说当年网景与 IE 大战,IE5.5 那是何等的风骚……(好吧,此处略去十页)。从维基百科的资料来看,IE5.5 beta1 的发布时间是:1999年12月,最终版本是 2000年7月。那么 W3C 标准中是什么时候才出现 inline-block 这个值的呢?
在 CSS1 规范中,「display」的值仅包括: block | inline | list-item | none 。CSS2.1中才添加了 inline-block 属性值。一丝继续舔着手指,用那苦逼的英语水平终于翻到了这份草案:http://www.w3.org/TR/2002/WD-CSS21-20020802/visuren.html#display-prop, 这份草案的日期是 2002年8月2日,纳尼!!!原来咱们纠结了半天的 inline-block , IE5.5 至少提早两年就提出来了啊!难道是微软给 W3C 提议后,CSS 2.1才加入的?(不过我看到 W3C 官网有一个关因而否增长 inline-block 的投票)好吧这个问题也许有一天 IE 某个开发者写《 IE回忆录》的时候咱们才能了解到其中的内幕。若是找到更早关于 inline-block 的 CSS草案,也麻烦告知一丝一声。好吧,若是你还不相信,打微软官方电话问问吧 800-820-3800(不是 DHC 哦!)。
原来咱们一直讨论的 inline-block 在 IE 六、7中和 CSS2.1 中的(现代浏览器所支持的) inline-block 上压根不是一个东东嘛,IE六、7 中的 inline-block 更像是 IE 的私有属性值,他们自己就不具备可比性。简单、绝对的认为 IE六、7 不支持 inline-block 比如一叶障目,看到前面,却看不到后面,太过于片面。诚然,IE六、7 的 hasLayout 给咱们带来了不少麻烦,可是不得不认可微软的 IE 在网页多语言文本混排上的先进性,尤为是 CJK 文字和西文的混排,超越其余浏览器至少5年。
总结:
各浏览器对 display 属性的支持状况请参阅:《各浏览器对 ‘display’ 特性值的支持程度不一样》
这么一个神奇的属性,为什么你们一直避而远之呢?这恐怕还得从 inline-block 元素之间产生的水平空隙(间隙)提及吧。
看看 inline 元素默认的表现状况如何?原来默认就有空隙存在!它们是谁?是空白符(white space)!
W3C 9.1 White space 中规定如下元素属于空白符(white space):
9.3.2 Controlling line breaks 中进一步阐述:
A line break is defined to be a carriage return ( ), a line feed ( ), or a carriage return/line feed pair. All line breaks constitute white space.
For more information about SGML’s specification of line breaks, please consult thenotes on line breaks in the appendix.
折行被定义为一个回车符( ),一个换行符 line feed ( ),或者一个回车、换行的组合。全部的折行构成了空白符。
有关 SGML 规范中折行的更多信息,请参阅附录中关于折行的注释。
一般状况下,对于多个连续的空白符(空格,换行符,回车符等),浏览器会将他们合并为一个空白符。CSS 中由 white-space 这个属性来控制:
white-space:normal | pre | nowrap | pre-wrap | pre-line
默认值:normal
注:IE7及更早浏览器不支持 CSS2.1 新增的 pre-wrap | pre-line。
因此这并非 inline-block 后产生的 bug,而是由于 inline-block 具备 inline 元素固有的特性。那么为什么 IE六、7 block 元素没有产生空隙呢?其实前面也提到了 IE 的 hasLayout,具备独立性,因此产生 hasLayout 的元素之间表现出来互不影响,这也再次代表 IE六、7 中的 inline-block 不能等同于 CSS2.1 中的 inline-block。若是非要说是有 bug, IE六、7 block 元素 inline-block 后不产生空隙才是 bug。
测试代表删除换行符后,inline 元素间的空隙就「消失」了:
为了让各个浏览器表现一致,更好的还原视觉设计搞,不少时候咱们须要去掉 inline-block 产生的空隙。
上一节中咱们已经知道产生空隙的根本性缘由是:
HTML 中的换行符、空格符、制表符等产生了空白符,而这些归根结底都是字符,那么它们的大小都是 受 font-size 来控制的,字体大小直接致使 inline 或者 inline-block 后元素之间空隙的大小,把 inline-block 元素间的空隙认为老是某个固定大小是错误的。
用 GIF 动画的形式来代表对应关系:
很清楚的看到,当 font-size:0 的时候元素间的空隙都为0了,或许到这里你会感到很欣喜了,原来掌握的根本性缘由这么简单就搞定了啊!
然,理想是丰满的,现实是骨感的。
大部分浏览器是支持 font-size:0 的。很明显,咱们要和 IE 六、7 这两个妖孽进行一番战斗。
font-size:0 的支持状况
1)Chrome
低版本的 chrome 浏览器为了避免让文字太小不利于阅读,默认是不支持 font-size:0 的,还好咱们有 -webkit-text-size-adjust 这个私有属性来控制,当设为 none 时就支持字体大小为 0 了。我已经记不清楚 chrome 从哪一个版本开始支持 font-size:0 了,反正我用 chrome 19 是支持了(有知道的朋友,烦请告诉一丝一声,最好有官方更新说明)。可是,-webkit-text-size-adjust:none; 会直接致使页面文字没法缩放,这对于用户来讲显然是不友好的。因此-webkit-text-size-adjust:none; 必定要慎用,确保使用的地方没有大面积的文字。
-webkit-text-size-adjust:none 的使用场景实例参阅:http://vip.etao.com/
2)Safari
Safari 5 依旧不支持 font-size:0 ,不过相信这些浏览器厂商都意识到了这个问题,在 Mac 平台最新的 Safari 6 已经很好的支持 font-size:0 了。
3)Firefox,Opera
经测试,Firefox12,Opera 10 ,此次表现不错,支持 font-size:0 。
4)IE
是否是一会儿又开始头疼了?不要紧,让咱们请出 letter-spacing 和 word-spacing 二位大神。既然空白符也是字符,那么二位大神确定是能够搞定它们的。
normal: 默认间隔
length: 用长度值指定间隔,容许为负值。
还等什么,咱们赶忙试试吧:
font-size:0;/* 全部浏览器 */
letter-spacing:-5px;/* Safari 等不支持字体大小为 0 的浏览器 */
*letter-spacing:normal;
word-spacing:-1px;/* IE六、7 */
.dib-wrap {
font-size:0;/* 全部浏览器 */
*word-spacing:-1px;/* IE六、7 */
}
.dib-wrap .dib{
font-size: 12px;
letter-spacing: normal;
word-spacing: normal;
vertical-align:top;
}
@media screen and (-webkit-min-device-pixel-ratio:0){
/* firefox 中 letter-spacing 会致使脱离普通流的元素水平位移 */
.dib-wrap{
letter-spacing:-5px;/* Safari 等不支持字体大小为 0 的浏览器, N 根据父级字体调节*/
}
}
.dib {
display: inline-block;
*display:inline;
*zoom:1;
}
其实在 YUI 3 中也全面运用了 inline-block 做为基础布局,YUI 3 是这样解决的:
.yui3-g {
letter-spacing: -0.31em; /* webkit: collapse white-space between units */
*letter-spacing: normal; /* reset IE < 8 */
word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
}.yui3-u {
display: inline-block;
zoom: 1; *display: inline; /* IE < 8: fake inline-block */
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
}
显然,这里纯粹使用了 letter-spacing 和 word-spacing 来控制元素间的空隙,局限性极大,-0.31em 和 -0.43em 只是由于 YUI 3 全局 cssfonts.css 里设置是:「body { font:13px/1.231 arial,helvetica,clean,sans-serif; }」。
固然,若是你坚持使用把 html 写在一行的方式来达到去除 inline-block 空隙的目的,我只能说:一切以牺牲结构来兼容表现的行为都是耍流氓!因此探讨此种方式去除空隙也将是无心义的,不在本文和做者考虑范围以内。
现在,Mac 平台下的 Safari 6 已经支持 font-size:0 了,相信很快 Windows 平台的 Safari 若是发布 5.X 的更新,也会支持字体为 font-size:0 了。等到 IE六、7 灭亡以后,世界就真真儿的美妙了!最后说一点:inline-block 与 float 也是没法直接比较的,请不要再讨论 inline-block 和 float 哪一个更好的话题了。inline-block 从 IE5.5 一路走来,存在便是合理,之后有时间在总结一下 inline-block 与 float 的使用场景的区别。
在不改变 CSS 定位机制的前提下,inline-block 应该是首选,而不是以「奇淫技巧」存在的。有感打油诗一首:
网事如烟
CSS 红尘里
inline-block 知多少
你在这头
inline-block 在那头
用与不用
它就在那里
不悲不喜
PS:
操做系统版本: | Windows 7 企业版 6.1(内部版本 7600) |
---|---|
浏览器版本: | IE6 IE9 Firefox 14.0.1 Chrome 19.0.1084.46 Safari 5.1.7(7534.57.2) Opera 12.50 |
最后更新时间: | 2012-8-22 |