标签: :before

水平且垂直居中 CSS 详解

自适应的水平垂直居中

旅行商人罗伦斯在马车货台上的麦束堆里,发现沉睡中的少女——自称是丰收之神赫萝的美丽少女,有着狼的耳朵及尾巴。

「虽然奴家长久以来被尊为神,不过,奴家就是奴家,奴家是赫萝。」

 

相比于水平居中用 margin:auto; 的简便,CSS 没有直接的垂直居中属性,必须通过各种诡异的技巧去实现,确实让人很头疼。以上算是一种实现方式,核心的代码如下:

 
这段代码中,最重要的是 .outer:before 这个伪元素。它起到了连接内外元素以及垂直对齐的作用。
 
需要明白的是,对一个 div 而言,它的伪元素会放在这个 div 包含的任何内容元素的前面,默认为 inline-block 元素(即“行内元素”或者“内联元素”)。示例:

执行结果:

元素内容

 
当元素内容为其它元素,尤其是块级元素时,则有内容的 :before 会在最顶上。

<p>元素块级内容</p>

 
再强调一遍,:before 其实是一个元素的子元素,永远排在其它实际子元素的前面,比如:

的实际执行效果如下:

是特殊的子元素

可以看到,对于 p 元素添加的 border,连 :before 这段文字也被包含在内。
 
现在再回头来看原始代码,如果把 :before 的部分修改一下,给 :before 元素加个边框,修改内容,使得识别更简单:

垂直居中

这样这段代码的原理就非常清楚了。首先,:before 伪元素和内部元素(通过 display:inline-block 设置为行内元素)共同构成了“一行文字”。其次,所有的行内元素都利用 vertical-align:middle 进行了垂直居中对齐。最后,再设置 :before 的高度使得它上下都顶到父元素的边框。这样,同一”行”内的其它元素在视觉就都相对父元素垂直居中了。其实它们在逻辑上真正对齐的对象是 :before。而 :before 自己,则被“卡”到了正中间的位置。
 
最后,由于 :before 在没有实际内容(通常用 ” ” 空格填充 content 属性)时其实也有宽度,所以在父元素上使用针对文本的 text-align: center; 虽然可以把左右居中也一起做掉。不过还是用常规的 margin:auto 更精确一点。解决办法是对 :after 伪元素也设置 content:” “。

PS:因为 ie6 不支持伪元素,所以……要不还是用 table 吧。