垂直居中发现一个奇怪的问题

http://jsfiddle.net/LaW2v/

这边第三个div的position是不起作用的,但是但第二个div加上高度就可以,这是为什么?

阅读 3.5k
2 个回答

LZ应该能注意到,如果第三个DIV的top值是其他单位的值,它的偏移是有效的吧?所以不是position不起作用,而是top不起作用。

第一,topbottomheight属性的百分比值是相对于包含块的高度计算的。

第二,包含块判定方式,见W3help知识库:包含块或W3C。

请输入图片描述

因此.three的包含块是.two的内容区域content-edge。

第三,position:absolute的元素有这样的特性:

  • 高度塌陷:它对外层不占位,无法撑高或者撑宽父级元素
  • 默认包裹:除非限制position:absolute元素的高宽,它的默认值width:auto;height:auto将导致它自己适应于自己的内容区域。

w3c: 10.6.7 'Auto' heights for block formatting context roots
If it has block-level children, the height is the distance between the top margin-edge of the topmost block-level child box and the bottom margin-edge of the bottommost block-level child box.

好的,我们可以画出依赖关系了:

  1. .two的高度——依赖于——>.three的高度(第3点,默认包裹)
  2. .three的偏移量——依赖于——>.two的高度(第1、2点,包含块计算)

这样看似可以得到一个.three的偏移量——依赖于——>.three的高度的结论。
实现方式还是跟浏览器有关的,需要看浏览器允不允许这种递归式的计算,height:auto参与计算的具体实现方式是怎样的。

根据我的测试,IE7能算出来期望的top值,而IE8/9,chrome、safari、firefox则都算出来为0。考虑到IE7以后CSS2.1才正式提出,可能相应标准中已经有阐述了(只是我没有找到)。如果W3C标准中有相应内容的阐述,请不吝指出。


最后,这个是满足不了垂直居中的需求的。你可能需要的是在.two上面加上transform:translateY(-50%)等属性,让它偏移自身高度的一半(或者手动算出这个值,用负margin来做)。

盒子two没有提供宽高。

* {
    margin:0;
    padding:0;
}
.one {
    width: 500px;
    height: 500px;
    margin: 0 auto;
    position: relative;
    border:2px solid red;
}
.two {
    height:100px;
    width:100px;
    position: absolute;
    top: 50%;
    border:2px solid green;
}
.three {
    position: relative;
    top:-50%;
    border:2px solid blue;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题