inline-block的使用及bug
2009 11 21 05:33 PM 6575次查看
首先来区分一下3者:
- inline元素:
- 紧接在内联元素前/后的文本和图片与内联元素的内容渲染为同一基准线。但如果该文本或图片过长,它们就会与包含元素的边缘相重叠,在这种情况下,内嵌内容就会跑到一条新基准线上面,而该基准线位于之前的那条基线的下面。(即一行显示不到时才换行。)
- 内联元素中,文本行的布置会视需要(或允许)而带有软换行符,除非用 white-space 属性修改了这种方式。
- 样式表规则中可应用于这些元素的margin、width、height和float属性被忽略。(除了img和object)
- 内联元素只能容纳文本或其它内联元素。
- 紧接在内联元素前/后的文本和图片与内联元素的内容渲染为同一基准线。但如果该文本或图片过长,它们就会与包含元素的边缘相重叠,在这种情况下,内嵌内容就会跑到一条新基准线上面,而该基准线位于之前的那条基线的下面。(即一行显示不到时才换行。)
- block元素:
- 这些元素将在其容器中渲染为离散块。
- 这些元素的前后将总是渲染有断行点,除非将float值设为left或right。
- 如果嵌套块元素之间没有任何内容,它们之间的断行点通常会被合并。
- 宽度为 auto(默认)的块元素会一直扩展,直到占满所有可获得的宽度。
- 这些元素将在其容器中渲染为离散块。
- inline-block元素:
- 将对象呈递为内联对象,但是对象的内容作为块对象呈递。旁边的内联对象会被呈递在同一行内,允许空格。
- 也就是说,它在文档中当成inline对象,可以被另一个inline对象包围;同时它内部是个block元素,因此可以包含block元素,也可以设置宽高。
- 将对象呈递为内联对象,但是对象的内容作为块对象呈递。旁边的内联对象会被呈递在同一行内,允许空格。
虽然想法是好的,可惜IE 7和Firefox 2及以前的版本是不支持inline-block的,所以才会有下面的问题。
考虑一个导航条,我需要它竖排显示,那么最容易想到的办法就是用无序列表实现,并在每个li里包含一个a元素。
那如果要在每行前加上一个图标呢?用img显得太笨重了(而且偏离了img的语义),用:before又会遇到兼容性问题(而且更笨重),用list-style-image又会遇到很多限制,用background-image似乎是个不错的选择。
于是将一个span放在a里面,将a设为block元素,并设置a的背景图像,加上background-repeat: no-repeat,可是什么效果都没有。
原来这个span是空的,浏览器会将宽高当成0而不显示。可span默认是个内联元素,要设置宽高就得转成块元素,而块元素又会自动换行,导致a变成2行。
看来要实现这个效果,得把span设为float: left,或者display: inline-block。
先使用float,似乎效果很好,但如果给span设置了左边距,会发现IE 6的左边距翻倍了,这是不能接受的。解决办法是将span设为inline元素。
实际上float元素是会被自动当成block元素的,即便改成inline也无效(用Chrome的审查元素功能可以看出),但IE 6非要这样设置才会正常。
至于float的其他bug就不管了,还是去看看inline-block吧。很奇怪的是,它在各种浏览器下似乎都不错,连IE 6也正常。(这里有个演示)
原来尽管IE 6不认识inline-block,却会因它而设置hasLayout(实际上非法的display值都会触发,并重设为默认的显示方式,因此你写display: abc也行)。这里有hasLayout的详细解释,我就不详述了,重点是hasLayout的元素可以设置宽高,而如果同时又inline,那么它的行为就和inline-block很类似了。
当然,我们运气很好,是将一个inline元素表现成inline-block元素,而如果要让一个block元素表现成inline-block元素则只能再加上display: inline来强行更改了。但注意它仍然是个inline元素,内部是不能包含block元素的。
此外,Firefox 2可以用display: -moz-inline-box、display: -moz-inline-stack(或许还要用到-moz-box-align: center和-moz-box-pack: center)来解决。
似乎一切都大功告成了,可还是发现一个问题,而且无论是float,还是inline-block都存在:在IE 6下,每个li之间有一个空行,而其他浏览器下则会有1px的空隙。
下面给个更清楚的例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>test</title>
<style type="text/css">
html, body, ul, li, div, span {margin:0; padding: 0; border: 0;}
div, span {background: #ccc;}
span.block {display: block;}
span.inline_block {display: inline-block;}
</style>
</head>
<body>
<ul>
<li><span>span 1</span></li>
<li><span>span 2</span></li>
</ul>
<ul>
<li><div>div 1</div></li>
<li><div>div 2</div></li>
</ul>
<ul>
<li><span class='block'>block span 1</span></li>
<li><span class='block'>block span 2</span></li>
</ul>
<ul>
<li><span class='inline_block'>inline-block span 1</span></li>
<li><span class='inline_block'>inline-block span 2</span></li>
</ul>
<ul>
<li><span class='block'>block span 3</span></li> <li><span class='block'>block span 4</span></li>
</ul>
<ul>
<li><span class='block'>block span 5</span></li><li><span class='block'>block span 6</span></li>
</ul>
</body>
</html>
它的表现很可怕,在IE 6、IE 7、Firefox 3.5和Chrome 4中各不相同…首先看最不标准的IE 6,一旦span被设为block,且使用了空格、换行等空白,那么在该元素下方就会多出一个空行。奇怪的是div元素却没受影响。
接着是IE 7,没有任何空白,感觉不错。
再看Firefox 3.5,在inline的span上方会有1px的空白。
最后看Chrome 4,在inline的span下方会有1px的空白。
这1像素还比较好解决,实际上它是span和li的高度不同导致的。默认状态下,span是inline元素,height为0,Chrome将其显示为19px高,而li的高度却显示成20px了。将li设置成19px高或更小即可解决该问题。
而那个空行的问题,最简单的办法当然就是删除空白了,但代码就不美观了。
其实归根结底,还是hasLayout的问题。将span设为block元素后,它仍然没有layout;于是给span.block加上个zoom: 1,触发layout后,便成功消除空行了。只是这个属性是IE私有的,无法通过W3C检查。所以继续改成height: 100%,则一切正常了。
此外,inline-block也能做到类似效果,只是不能扩展到整个父元素。让它扩展只能设置witdh了,这里设为100%是可行的,因为边距、边框和填充距都是0;但如果这些不为0的话,得计算一下,用父元素减去这些距离。
0条评论 你不来一发么↓