垂直居中作为一个常见布局形式,或多或少的会给不熟悉页面布局的人带来困扰,这里参考Steven Bradley总结的六种布局方法,带给大家一些新的思考。这里介绍的方法都是常规的CSS方法,可以垂直居中行内元素以及块级元素,实际上CSS3的flex布局方法可以完美解决类似垂直居中,水平居中,分散对齐等常见的布局形式,具体可以参看阮一峰老师的这篇文章Flex 布局教程。
正文
通过CSS实现水平居中相当简单。当被居中的元素是内联元素(行内元素)时,我们可以使用text-align:center
在父元素中水平居中。当元素是一个块级元素时,我们给定它的宽度,然后把它的左边距和右边距设置成auto
,也可以实现水平居中。
考虑到text-align:center
可以水平居中,为了垂直居中大部分人首先想到的应该是vertical-align属性。看起来很符合逻辑,如果你熟悉表格布局,你很有可能使用过valign
属性,这样也会让你相信vertical-align
应该也是这样。
然而valign
只对表格单元有效,vertical-align
也是类似的,它即对表格单元有效,又对一些内联元素有效。
vertical-align
值的意义和其父级内联元素有关。
- 在一行文本内,其值是相对于行高的。
- 在一个表格单元内,其值是相对于表格高度算法,通常是指一行的高度。
很遗憾vertical-align
对块级元素不起作用,像一个div里面的段落。我们大多数可以想出来,这并不是所有的解决方案。
尽管我们有其他方法居中块级元素,我们仍然可以在恰当的时候使用vertical-align
。选择那个方法主要依赖于你想居中在何种容器元素中。
关于vertical-align更多介绍,可以看看鑫大神的文章,点这里
1.line-height方法
这种方法适用于垂直居中单行文本的情况。我们要做的只是给包含文本的元素设置一个行高(line-height
),只要保证行高大于文本的字体大小就可以了。
通常情况下,文本的上下会有相同的间距,文本刚好垂直居中。
大部分方法都建议把元素的height
和元素的line-height
设置成一样的值。我认为设置height
是没有必要的,但是如果仅仅设置line-height
不起作用,设置height
可能就是解决办法(这样看来,最好height
,line-height
都设置,并且值保持一致)。
html
<div id="parent">
<div id="child"> Text here </div>
<div>
css
#child{
line-height: 200px;
}
上面的代码可以运行在任意的浏览器中,但是它只对单行文本有效,如果文本换行你必须使用另外的方法。200px是随意设置的,你可以设置成任意大于字体大小的值。
2.css table方法
通过在table cell元素上应用vertical-align
属性来实现。
html
<div id="parent">
<div id="child">Content here</div>
</div>
css
#parent {display: table;}
#child {
display: table-cell;
vertical-align: middle;
}
把父级div的display
设置成table
,把子级div的display
属性设置成table-cell
。然后在子级div上应用vertical-align
属性,并且设置成middle
。这样子级div就相当于一个垂直居中的容器,你可以往里面放任意内容包括行内元素,块级元素,并且这些内容都是相对父级div元素垂直居中的。
这种方法存在兼容性问题,只对IE8+起作用。
3.absolute定位和负margin方法
这种方法适用于块级元素,并且对任意浏览器都有效。唯一的要求是必须设置垂直居中的块级元素的高度。
其实用这种方式既可以垂直居中块级元素,又可以水平居中块级元素;垂直居中块级元素,那么块级元素必须设置高度;水平居中块级元素,那么块级元素必须设置宽度。
html
<div id="parent">
<div id="child">Content here</div>
</div>
css
#parent {position: relative;}
#child {
position: absolute;
top: 50%;
left: 50%;
height: 30%;
width: 50%;
margin: -15% 0 0 -25%;
}
首先设置父级以及子级div的position
属性;然后把子级div的top
属性left
属性都设置为50%,这样的话子级div快的左顶点就在父级div块的中间位置了;接下来要做的就是把子级div往上移动其半个高度,往左移动其半个宽度,此时子级div块才算在父级div块的中间了。这也是为什么一定要先知道子级div块高度和宽度的原因。
为了做到上面的第三步,可以设置子级div块的top margin
等于负的高度的一半,left margin
等于负的宽度的一半。
和第二种方法不同,这种方法适用与块级元素。然而如果子级div的大小比父级div的大小要大,那么子级div会有一部分内容看不到,所以使用这种方式你最好知道子级div块的宽高。
4.absolute定位和拉伸方法
使用这种方式必须把父级元素设置成relative
定位,把子级元素设置为absolute
定位。
下面的代码既可以垂直居中,也可以水平居中。
html
<div id="parent">
<div id="child">Content here</div>
</div>
css
#parent {position: relative;}
#child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 50%;
height: 30%;
margin: auto;
}
这种方法的原理是通过设置子元素距父元素4条边的top
,left
,bottom
,right
值为0,而让子元素自动向四条边拉伸,因为字元素比父元素要小,所以不能触碰到任意一条边。
把margin
设置成auto
,可以让每个相对边的margin
值一样,这样就可以让字div在父div中居中。
另外这种方法不支持IE8以下版本的IE浏览器,并且也有上面的方法中存在的问题,就是如果字元素中内容很长,会导致超出内容不可见。
5.设置相同的padding-top和padding-bottom方法
在上面的方法中,我们让浏览器自动设置子元素的margin
值,所以可以保证margin值是相同的。这个方法要做的也类似,只不过要确切的设置父元素的top
和bottom
的padding
值。
html
<div id="parent">
<div id="child">Content here</div>
</div>
css
#parent {
padding: 5% 0;
}
#child {
padding: 10% 0;
}
在上面的css中子元素父元素都设置了padding-top
和padding-bottoom
值。设置子元素的padding
可以确保子元素的内容垂直居中,设置父元素的padding
可以确保整个子元素在父元素中居中。
示例中使用了相对单位,允许每个div的padding
自动变化。如果需要设置绝对地址,你需要计算出正确的padding
值。设置子元素的padding
可以确保子元素的内容垂直居中,设置父元素的padding
可以确保整个子元素在父元素中居中。
例如,如果父元素的高度是400px,子元素的高度是100px,那么子元素和父元素的padding-top
和padding-bottom
值应该设置为150px。
150 + 150 + 100 = 400
此时如果还用百分比的话,就不能居中了,除非这个百分比算出来的值刚好等于150px。
这个方法适用于所有的浏览器。缺点就是有点计算量。
注意:这种方法是通过设置包裹元素的padding
来实现的,这样的话,你就不用再设置内部元素有相同的margin了。这里虽然使用了padding
来实现,实际上也可以设置margin
来实现,主要依赖代码需要。
6.浮动div方法
最后一种方法需要一个空的浮动的div,用来控制子元素在文档流的那个位置。注意浮动div必须在子元素前面。
html
<div id="parent">
<div id="floater"></div>
<div id="child">Content here</div>
</div>
css
#parent {height: 250px;}
#floater {
float: left;
height: 50%;
width: 100%;
margin-bottom: -50px;
}
#child {
clear: both;
height: 100px;
}
设置一个浮动的子div元素,并且设置其高度等于父div元素的50%。这样子div元素就会充满父div元素的上半部分。
因为这个子div元素从正常的文档流中移除了,所以我们需要清除其它子元素两边的浮动,这里使用了clear:both
,但是实际上只需要清除和浮动元素相同方向上的浮动就可以了。
此时另一个非浮动子div元素的上边框应该与浮动子div元素的下边框重合,然后需要把非浮动子div元素往上移动其高度的一半,可以通过设置浮动子div元素的margin-bottom
值为负的非浮动子div元素高度的一半来实现。
这种也适用于所有浏览器,但是缺点就是需要一个空的浮动div元素,然后你需要知道子div元素的高度。