overflow:hidden 影响inline-block元素周围元素下移

前言:

最近在切页中,我想实现左边一个类似下拉选框,且不允许输入,右边有一段垂直居中的文字描述的效果。我对文字用的是p标签。其实可以用个i/b/em等其他行内标签,同时也具有一定语义,做为强调提示,(当时事实证明用行内标签问题一样存在)。最后我的问题出现了。一个设置了overflow:hidden 的inline-block元素旁边的文字与边框的下边放佛是对齐的。因为vertical-align属性的默认值时baseline,同是文字又只有一行那么它们的baseline应该是对齐的啊!!     

当修改元素的vertical-align属性为baseline以外的其他值时可以看到文字相对边框的垂直位置发生了变化。初步能确定是跟对齐方式有关,并且是由于基线(baseline)的位置发生了变化而不再是原来的以x的下边线做为基线了。那么是什么原因造成位置的偏移呢?经过测试,发现是overflow:hidden的这个属性影响了inline-block元素baseline的位置。那么overflow:hidden的inline-block元素的baseline怎样设置的呢?请继续往下读......

问题描述:

overflow:hidden怎样影响inline-block的baseline的位置。导致文字不与inline-block的文字的对齐,而是向下偏移。

化繁为简,代码如下,效果运行请看demo

html结构

<div class="div1">
  我是div1
</div>
<div class="div2">
  我是div2
</div>

css 样式

.div1 ,
.div2 {
	display: inline-block;
}
.div1 {
	 180px;
    height: 40px;
    line-height: 40px;
    overflow: hidden;
    border: 1px solid #000;
}

  

 

div2和左边的框中间没对齐。 默认对齐方式是baseline.

原因:

vertical-align的默认值是baseline。当div1 设置了属性overflow:hidden后,baseline会设置在bottom margin的边缘。详情戳css规范

规范的截图:

翻译:'inline-block'(盒)的基线是它的最后一个常规流中的行盒的基线除非它没有流内行盒或者它的'overflow'属性的计算值不为'visible',此时基线是bottom margin边。

所以div2的文字和div1的下边框对齐。

注意:如果元素内部只有脱离常规流的行盒,如被设置了float 除了none以外的值,position为fixed和absolute,也会出现同样的情况。demo

解决方案:

方案1.将设置了overflow:hidden的元素 的垂直对齐方式设置为vertical:middle;将该盒的竖直中点与父级元素的baseline对齐。demo2.

此方案需要写的代码少,当它周围有其他元素的时候,也能解决。 兼容问题,在支持inline-block的浏览器中都支持。想要ie 6,7兼容可以触发haslayout,并将元素用ie6、7的hack设为inline盒模型。使其表现出inline-block的特性。

代码如下:

.div1,
.div2 {
  display: inline-block;
  *display: inline;  /*ie7及以下浏览器 以内联盒模型渲染*/
  *zoom: 1;   /*触发ie的haslayout*/
}
.div1 {
   180px;
  height: 40px;
  line-height: 40px;
  overflow: hidden;
  border: 1px solid #000;
  vertical-align: middle;
}

  

方案2. 稍微麻烦点,对受影响的另一个inline-block的元素处理,让它的line-height和div1的height相同。并且让自己的垂直对齐方式为vertica-align:middle;   demo3

.div1,
.div2 {
  display: inline-block;
  *display: inline;  /*ie7及以下浏览器 以内联盒模型渲染*/
  *zoom: 1;   /*触发ie的haslayout*/
}
.div1 {
   180px;
  height: 40px;
  line-height: 40px;
  overflow: hidden;
  border: 1px solid #000;
  vertical-align: middle;
}
.div2 {
 line-height: 40px;
 vertical-align: top;
}

 此方法,只是让它看起来在旁边盒子的垂直中点位置,且如果旁边的元素比较多,要为这些元素一一设置属性。不建议使用。

 延伸问题:

如果inline-block元素旁边的是inline元素,有同样的影响吗?

答案是 yes ,请看demo4,原因也是同上。

 关于baseline 怎么确定,规范上没有具体定义,user agent自己规定。

以下摘自w3c规范

内联格式化上下文节所述,用户代理把内联级盒排列在一个行盒的垂直堆叠里。行盒的高度由下列规则决定:

  1. 计算行盒中每个内联级盒的高度时,对于可替换元素,inline-block元素和inline-table元素,这个值就是其margin box的高度;对于内联盒,这个值是其'line-height'(见“计算height与margin”“行距(Leading)与半行距”中的内联盒的高度
  2. 内联级盒是根据其'vertical-align'属性竖直对齐的。如果它们是'top'或者'bottom'对齐,它们必须对齐得让行盒高度最小化。如果这样的盒足够高,存在多个解,而CSS 2.1没有定义行盒基线的位置(即,strut的位置,见下文)
  3. 行盒高度是最高的盒的top与最低的盒的bottom之间的距离(包括下面'line-height'中解释的strut

空内联元素生成空的内联盒,但这些盒仍然具有margin,padding,border和line height,并因此会影响这些计算,就像有内容的元素一样。

 补充 strut:对于一个内容由内联级元素组成的块容器元素,'line-height'指定了元素内行盒的最小高度。这个最小高度包含基线上方的最小高度和下方的最小深度,就像每个行盒以一个具有该元素的字体和行高属性的0宽内联盒开始。我们把这种假想盒叫做"strut"(这个名字是受TeX的启发)。  

参考资料:

https://www.w3.org/TR/CSS2/visudet.html#strut

http://blog.csdn.net/iefreer/article/details/50421025

原文地址:https://www.cnblogs.com/AliceX-J/p/5731755.html