inline-block元素间间隙产生及去除详解:

浏览器参照基准:Firefox, Chrome, Safari, Opera, IE

* inline-block 即内联块,可以水平排版

Figure 1:定义一个inline level元素为内联块 DEMO
<div id="demo"> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> </div> #demo span{ display:inline-block; }

* 对于inline level的元素,所有主流浏览器都支持直接设置display 的value值为inline-block来将其定义为内联块;

Figure 2:定义一个block level元素为内联块 DEMO
<div id="demo"> <div>我是一个div</div> <div>我是一个div</div> <div>我是一个div</div> <div>我是一个div</div> </div> #demo div{ display:inline-block; *display:inline; *zoom:1; }

* why? 细心的你可能发现定义inline level和block level为inline-block(内联块)代码是有所区别的。OK, 很遗憾的告诉你,IE7及以下浏览器对inline-block的支持并不完全,它们只支持用display:inline-block去定义一个inline level的元素为内联块;

曲线救国:由于IE7及以下浏览器支持直接将inline level元素设置为内联块,所以我们可以变通实现,先将block level元素设置为inline,然后再去触发该元素的hasLayout,使其拥有和inline-block相似的特性;

Figure 3:间隙 DEMO
<div id="demo"> <div>我是一个div</div> <div>我是一个div</div> <span>我是一个span</span> <span>我是一个span</span> <div>我是一个div</div> <span>我是一个span</span> </div> #demo span,#demo div{ display:inline-block; *display:inline; *zoom:1; }

* inline-block元素间出现间隙:从Figure #1DEMO,我们发现每个span之间都出现了几像素的空白间隙;从Figure #2DEMO,我们发现除IE7及以下浏览器外,所有浏览器表现和Figure 1一致;再来看本例Figure #3DEMO,我们似乎可以找到间隙出现的规律;

* IE7及以下浏览器很坑爹:block level元素转换为inline-block,在IE7及以下浏览器下元素间不出现间隙;inline level元素转换为inline-block,在IE7及以下浏览器下元素间出现间隙;紧跟block level转换为inline-block的元素之后有个inline level转换为inline-block的元素,在IE7及以下浏览器下这俩元素间不出现间隙;紧跟inline level转换为inline-block的元素之后有个block level转换为inline-block的元素,在IE7及以下浏览器下这俩元素间出现间隙;其它浏览器任何情况下均出现间隙;

* 注意:如果你要处理这个间隙,还得注意被转换为inline-block的元素,原本是inline level还是block level;

Figure 4:间隙由来 DEMO
<div id="demo"> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> </div>

* 在本例中,我们不对span做任何处理,你会发现span元素间也存在间隙,你有否怀疑这是由于换行导致?OK,我们来验证下这个疑问;

Figure 5:换行导致间隙? DEMO
<div id="demo"> <span>我是一个span</span><span>我是一个span</span><span>我是一个span</span><span>我是一个span</span> </div>

* 在本例中,我们只是将上例Figure #4中span写到同一行,运行本例Figure #5DEMO,间隙没有了;所以说间隙是由换行或者回车导致的,应该无大问题;

Figure 6:干掉间隙方案1: 约定书写方式 DEMO
<div id="demo"> <div>我是一个div</div><div>我是一个div</div><span>我是一个span</span><span>我是一个span</span><div>我是一个div</div><span>我是一个span</span> </div>

* 通过Figure #5及其DEMO,我们知道:将html写在一行,不动css,这种方案是最直接的解决方案,但却也是最不靠谱的方案,存在很多不可控因素。很多场景会让你崩溃:前后端协同;版本更迭;他人接手;自己忘了...,太多一不小心都可能让这个方案失效。尤其对于有代码洁癖的前端来说,这种方式简直让人难以忍受,你觉得呢?

Figure 7:干掉间隙方案2: font-size:0 DEMO
<div id="demo"> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> <span>我是一个span</span> </div> #demo{ font-size:0; } #demo span{ display:inline-block; *display:inline; *zoom:1; font-size:14px; }

* 奇怪?为什么font-size会对间隙有影响。如果你看到Figure #5及其DEMO,会知道space是由换行或回车所产生空白符所致,既然是字符当然无法摆脱font的控制(space是固定值?space值会否因font-size不同而变化?看DEMO),当然你也可以试验下诸如:font-family; font-weight等font系属性的影响;

* 该方案存在的问题,font-size要被overwrite一次;IE7及以下浏览器依然会残留1px的间隙;较老版本的webkit对小于12px的font-size设置不友好: chrome还可以设置-webkit-text-size-adjust:none用以支持超小字体,Safari即使设置了也无力;

* IE8及以上浏览器, Firefox, Opera, Safari6, Chrome18均可直接使用此方案;

Figure 8:全IE兼容方案1: font-size + 负margin DEMO
#demo{ *padding-left:1px; font-size:0; } #demo span{ display:inline-block; *display:inline; *zoom:1; *margin-left:-1px; font-size:14px; }

* 本例在Figure #7的方案上进行升级,针对IE7及以下浏览器hack,让每个inline-block的span元素向左负margin一个像素,借此修复IE7及以下浏览器下顽固的残留1px间隙问题。由于span向左margin了-1px,同时需将父元素#demo向左padding 1px,用于抵消位置偏移。

* 此方案会有一个隐患,你想到了吗?回头看Figure #3及其DEMO,所以如果你想要代码通用且健壮,该方案不应该成为最佳实践。

* IE, Firefox, Opera, Safari6, Chrome18均可直接使用此方案;

Figure 9:全IE兼容方案2: font-size + word-spacing DEMO
#demo{ *word-spacing:-1px; font-size:0; } #demo span{ display:inline-block; *display:inline; *zoom:1; word-spacing:normal; font-size:14px; }

* 本例仍然在Figure #7的方案上进行升级,我们知道inline-block之间的间隙是因插入了空白换行或回车符所致,你可能很快就能想起有个word-spacing属性是用来处理单词间空白符的。针对IE7及以下浏览器hack,定义word-spacing为-1px,即可修复IE7及以下浏览器下顽固的残留1px间隙问题。

* 由于word-spacing属性是用来处理单词间空白符的,所以一般如果子元素内只是纯粹的文字排版的话,子元素可以不将word-spacing的值还原成normal,除非子元素内部也有空白符或其它复杂情况;为了代码更健壮,建议直接将子元素还原成normal而不用去care各种场景。这里原本只需要for IE7-进行设置,但因为word-spacing的默认值就是normal,所以可以不必写成hack,因为该值不影响其它任何浏览器。

* IE, Firefox, Opera, Safari6, Chrome18均可直接使用此方案;

Figure 10:全浏览器兼容方案 DEMO
#demo{ font-size:0; [;font-size:12px;]; *font-size:0; font-family:arial; [;letter-spacing:-3px;]; *letter-spacing:normal; *word-spacing:-1px; } #demo span{ display:inline-block; *display:inline; *zoom:1; font-size:14px; letter-spacing:normal; word-spacing:normal; }

* 现在我们似乎只有较低版本的Chrome和Safari没有兼容了。还记得前面说它们对小于12px的字号支持无力,并且font-family指定字体不同,间隙也会随之而变;同时为了避免受到上下文font设置影响,在局部我们将之设置为12px的arial,为什么选择arial?主要是为了兼容尽可能多的平台,通常windows和Mac OS都会有arial字体,选择Arial字体后间隙将变成3px,对于子元素你仍然可以重置为想要的字体;这样无论外部环境如何变化,这个间隙将始终是3px (字体与间隙对应表,感谢勤劳的 一丝 同学整理这个表),不必因环境不同再去做调整。

* OK, 我们先将Chrome和Safari的字号设置为12px,这是一个hack [;font-size:12px;];,详情可参考属性级Hack,因为IE7及以下浏览器也能识别该hack,所以用 *font-size:0 重置一次;在Figure #9的时候测试了word-spacing对Chrome和Safari的间隙调整均皆无力,于是只好用letter-spacing来替代了;

* 所有主流浏览器均可直接使用此方案;

CSS探索之旅