We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
对于当今出现的一些CSS垂直居中的方案,这篇文章将会系统地审视它们,从实用角度进行评估。
不罗嗦,先上图:
为避免混淆,本文中所说的父容器和子容器都不是相对的,而对应着如下文档结构里面的.outer和.inner容器:
父容器
子容器
.outer
.inner
<div class="outer"> <!-- 父容器 --> <div class="inner"> <!-- 子容器 --> ... <!-- 子容器内部内容 --> </div> ... <!-- 父容器内其他的子元素 --> </div>
我们从如下角度来评估:
height:100px;
height:auto
height:50%
出现了 3(定高/自适应于外部/自适应于内部) ^ 2 (父容器/子容器) =9 种情形,搭配见下:
3(定高/自适应于外部/自适应于内部) ^ 2 (父容器/子容器) =9
子容器溢出代表子容器高度大于父容器高度的情形。
overflow:hidden
height:auto;overflow:visible
display:table-cell
overflow:scroll
overflow:auto
很显然,子容器溢出时,被父容器截断的情形无法和父容器自适应于子容器共存。
4、3、2、1的兼容难度是一步步变难,兼容到4、3、2、1所对应的代码量/工作量是100%、102%、120%、300%的关系。
在这里仅仅考量IE6/7,IE8的无bug实现的兼容性。IE9+的兼容性,对于文中提到的所有方案都是可行的。
如果需要手动计算,若界面进行重构,而居中的需求不变,就需要重新计算。比较费时费事。布局也相对不够灵活。
<td>√</td>
最基础的方案就是这样,手工算好每一个容器的高度和补白/位移需要的内容,简单粗暴:
/*父子均定高,父容器上下等padding*/ .outer{ height: 100px; padding-top: 40px ; } .inner{ height: 100px; }
/*父子均定高,子容器上下等margin*/ .outer{ height: 180px; overflow: hidden; *zoom: 1; }/*父容器给予BFC以避免子容器margin并到父容器上*/ .inner{ height: 100px; margin-top: 40px ; }
父子都需要自适应于内部时:
/*父子均自适应于内部,父容器上下等padding*/ .outer{ height: auto; padding-top: 40px ; padding-bottom: 40px ; } .inner{ height: auto; }
/*父子均自适应于内部,子容器上下等margin*/ .outer{ height: auto; overflow: hidden; *zoom: 1; }/*父容器给予BFC和haslayout,以避免子容器margin并到父容器上*/ .inner{ height: auto; margin-top: 40px ; margin-bottom: 40px ; }
说明:
height:auto;width:auto;
padding-top
padding-bottom
margin-top
margin-bottom
在子容器是<img>标签时,可以直接使用background来替代它。也可以算得上一种方案。
<img>
.inner { background-image: url("..."); background-position: 50% 50%;/*注,火狐不支持background-position-y的属性设置*/ }
“父容器line-height=height”,这个方案在于将子容器当做行内元素呈递,并设置vertical-align,line-box和block-box的高度持平,就完成了垂直居中的的效果。
.outer { line-height: 100px; height: 100px; font-size: 0; } .inner { display:inline-block; vertical-align:middle; font-size: 16px; }
为何需要font-size:0?因为vertical-align:middle的定义是:元素的中垂点与父元素的基线加1/2父元素中字母x的高度对齐。因此在font-size>0时,元素将会在baseline上出现一定的偏移,偏移量跟这个字号下的x字母的高度有关。
可以在jsFiddle中看到对比:
不使用font-size:0:
font-size:0
http://jsfiddle.net/humphry/haaaM/
使用font-size:0:
http://jsfiddle.net/humphry/7zCEm/
inline-block
vertical-align
line-height
font-size
对上面的方法不兼容IE6\7且不能做到父容器自适应的方面,可以这样改进:
:before
:after
<span>
inline-box
height:100%
vertical-align:middle
http://jsfiddle.net/humphry/86dsC/21/
现在这个布局可以自动生成,详见@林小志的css小工具:图片垂直居中span。
(如果需要水平居中,那么这个额外的节点,需要移去自身所占的距离,一般使用margin-left:-1px或margin-right:-1px,取决于钩子在子容器的哪一边。)
margin-left:-1px
margin-right:-1px
 
	

​
display:inline-block
这个方案依然是用到vertical-align:middle,只不过需要放到作为display:table-cell的元素之上。
http://jsfiddle.net/humphry/7AMF9/2/
这个布局也可以自动化生成:见@林小志的css小工具:图片垂直居中 table cell
display:table
为了可以让子容器有百分比高度,我们可以直接构建一个表结构出来:
http://jsfiddle.net/humphry/Ns4RK/8/
table
<table>
.outer{ position: relative; } .inner{ position: absolute; top: 50%; height: 20px; margin: -10px; }
这是互联网上能找到的最多的关于垂直居中的方法。我们不相信浏览器,使用手算,将子元素挪去自身高度的50%。
position
.outer{ position: relative; } .inner{ position: absolute; margin-top: auto; margin-bottom : auto; top: 0; bottom: 0; height: 20px; }
这个的原理写在CSS2.1中:
‘top’ + ‘margin-top’ + ‘border-top-width’ + ‘padding-top’ + ‘height’ + ‘padding-bottom’ + ‘border-bottom-width’ + ‘margin-bottom’ + ‘bottom’ = 包含块的高度
在其他值不是auto的时候,margin-top和margin-bottom是可以根据上式算出的,原理类似于水平居中。
top
bottom
margin
.outer{ position: relative; } .inner{ position: absolute; top: 50%; transform: translateY(-50%);}
原理同上,仅仅是仅仅是用translate替换了负margin,因为translate的百分比偏移量是容器本身的。
translate
.inner{ -webkit-transform:translate(-50%, -50%); -moz-transform:translate(-50%, -50%); -ms-transform:translate(-50%, -50%); -o-tranform:translate(-50%, -50%); transform:translate(-50%, -50%); }
.inner{ background-image: url("...") ; background-size: cover ; height: 100% ; }
background-clip
// TBD // 很抱歉,由于对flexbox没有深入的了解,我还没有试验出flexbox在子元素溢出时也能保持居中的解决方案……最好的结果是子元素被拉伸(= =)。有人有过实例吗?
The text was updated successfully, but these errors were encountered:
No branches or pull requests
对于当今出现的一些CSS垂直居中的方案,这篇文章将会系统地审视它们,从实用角度进行评估。
不罗嗦,先上图:
考量需求及难度
为避免混淆,本文中所说的
父容器
和子容器
都不是相对的,而对应着如下文档结构里面的.outer
和.inner
容器:我们从如下角度来评估:
高度相关
height:100px;
height:auto
height:50%
出现了
3(定高/自适应于外部/自适应于内部) ^ 2 (父容器/子容器) =9
种情形,搭配见下:溢出相关
子容器溢出代表子容器高度大于父容器高度的情形。
overflow:hidden
。height:auto;overflow:visible
或display:table-cell
等等。overflow:scroll
或overflow:auto
很显然,子容器溢出时,被父容器截断的情形无法和父容器自适应于子容器共存。
兼容性
4、3、2、1的兼容难度是一步步变难,兼容到4、3、2、1所对应的代码量/工作量是100%、102%、120%、300%的关系。
在这里仅仅考量IE6/7,IE8的无bug实现的兼容性。IE9+的兼容性,对于文中提到的所有方案都是可行的。
其他
如果需要手动计算,若界面进行重构,而居中的需求不变,就需要重新计算。比较费时费事。布局也相对不够灵活。
方案汇总
方案评估
1. 普通流,块级布局 (css2.1)
1.1. 父容器上下等padding & 子容器上下等margin
最基础的方案就是这样,手工算好每一个容器的高度和补白/位移需要的内容,简单粗暴:
父子都需要自适应于内部时:
说明:
height:auto
可以省去,这是默认值。对于块级元素,默认是
height:auto;width:auto;
width的auto值是自适应于这个元素的包含块的宽度,而height自适应于这个元素的content-box的高度
因为
height:auto
时,计算高度值的依赖方向是从外往内。因为对于height来说,它的百分比值是乘以包含块的height,但
padding-top
/padding-bottom
/margin-top
/margin-bottom
的百分比值是乘以包含块的width,而非我们希望的height。1.3. background代图片background-position
在子容器是
<img>
标签时,可以直接使用background来替代它。也可以算得上一种方案。说明:
2. 普通流,行内布局 (css2.1)
2.1 父容器line-height=height
“父容器line-height=height”,这个方案在于将子容器当做行内元素呈递,并设置vertical-align,line-box和block-box的高度持平,就完成了垂直居中的的效果。
为何需要font-size:0?因为vertical-align:middle的定义是:元素的中垂点与父元素的基线加1/2父元素中字母x的高度对齐。因此在font-size>0时,元素将会在baseline上出现一定的偏移,偏移量跟这个字号下的x字母的高度有关。
可以在jsFiddle中看到对比:
不使用
font-size:0
:http://jsfiddle.net/humphry/haaaM/
使用
font-size:0
:http://jsfiddle.net/humphry/7zCEm/
说明:
inline-block
和vertical-align
的标准诞生于IE8之后),也没有时间研究。2014年了,有点追求好吗。line-height
的百分比单位是相对font-size
来说的。line-height
和font-size
是一个可以继承的属性,在这种方案里面,必然会导致line-height
、font-size
被继承,因此在需要排版子容器时,需要复写line-height
、font-size
。2.2 子容器所在的line-box的line-height=父容器的height
对上面的方法不兼容IE6\7且不能做到父容器自适应的方面,可以这样改进:
:before
/:after
伪元素自制一个文本节点、或<span>
或任意一个inline级别的标签、或者一个1*1的图片。inline-box
元素,然后设置height:100%
即可。vertical-align:middle
,让它们的中心线对齐于于父容器的middle-line,就能做到垂直居中。http://jsfiddle.net/humphry/86dsC/21/
现在这个布局可以自动生成,详见@林小志的css小工具:图片垂直居中span。
(如果需要水平居中,那么这个额外的节点,需要移去自身所占的距离,一般使用
margin-left:-1px
或margin-right:-1px
,取决于钩子在子容器的哪一边。)说明:
 
)、ASCII 制表符 (	
)、ASCII 换页符 (
)、零宽度空格 (​
) 会被浏览器解析成一个空格,造成间隙。需要通过改变HTML结构/使用负margin等来去掉这个间隙。display:inline-block
的IE6\7 hack是另一部分。3. 普通流,块级table布局 (css2.1)
3.1. 父容器display:table-cell,子容器vertical-align
这个方案依然是用到
vertical-align:middle
,只不过需要放到作为display:table-cell
的元素之上。http://jsfiddle.net/humphry/7AMF9/2/
这个布局也可以自动化生成:见@林小志的css小工具:图片垂直居中 table cell
说明:
display:table-cell
。display:table-cell
的元素的包含块是它父级的display:table
的元素。3.2. 子容器被table、tr、td包裹
为了可以让子容器有百分比高度,我们可以直接构建一个表结构出来:
http://jsfiddle.net/humphry/Ns4RK/8/
说明:
table
。<table>
换成display:table
的其他元素,tr、td亦然:http://jsfiddle.net/humphry/KxKc8/
个人觉得……徒增烦恼尔。
4. 绝对定位布局 (css2.1)
4.1 子容器绝对定位,top:50%,负margin
这是互联网上能找到的最多的关于垂直居中的方法。我们不相信浏览器,使用手算,将子元素挪去自身高度的50%。
说明:
position
,这就意味着IE6\7下面的数十个友情附赠的美好bug。margin-top
的百分比,是相对其包含块的宽度而言的。4.2 子容器绝对定位,top:0,bottom:0,margin:auto
这个的原理写在CSS2.1中:
‘top’ + ‘margin-top’ + ‘border-top-width’ + ‘padding-top’ + ‘height’ + ‘padding-bottom’ + ‘border-bottom-width’ + ‘margin-bottom’ + ‘bottom’ = 包含块的高度
在其他值不是auto的时候,
margin-top
和margin-bottom
是可以根据上式算出的,原理类似于水平居中。说明:
top
、bottom
属性的样式解析与 css2.1 不一致,不支持这种定位方式。height:auto
,因为这样会使得上面的算式里auto出现在三个地方,浏览器无法计算出相应margin
值。5. css3一系列布局
5.1 子容器绝对定位,top:50%,translateY(-50%)
原理同上,仅仅是仅仅是用
translate
替换了负margin
,因为translate
的百分比偏移量是容器本身的。说明:
5.2 backgournd代图片,backgournd-size
说明:
background-clip
指定背景从哪里消失。.inner
的标签省掉,直接把背景放到.outer
之上5.3 flexbox
说明:
The text was updated successfully, but these errors were encountered: