CSS之水平垂直居中
在 css 的世界里,如果我们想让一个块级元素水平居中,想必大家都知道利用 margin:0 auto; 嘛,这样就可以让块级元素在它的父元素中水平居中了。
列如这样:
<!DOCTYPE html> <head> <title>center</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style> .parent { width:50%; height:100px; border:1px solid black; position:relative; } .child { margin:0 auto; width:50px; height:50px; background:#22B14C; } </style> </head> <body> <div class="parent"> <div class="child"><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
</html>
运行效果图如下,绿色方块水平居中于它的父元素
咦,那么问题来了,我们想要绿色方块垂直居中或者水平垂直居中呢?
是不是只要设置 margin:auto 0; 或 margin:auto; 就可以了呢?
曾经我也是这么以为的,因为设置 margin:0 auto; 可以水平居中嘛。
但是垂直居中就不是这么回事啦。
在普通文档流中,倘若你设置 margin:auto,其实浏览器解析时,会理解为 margin:0 auto;
(将 margin-top 和 margin-bottom 设置为 0,而 margin-left 和 margin-right 设置为左右自适应)。
摘自W3.org
如果你心存顾虑,可以将上面 demo 中的 margin:0 auto; 换成 margin:auto;,运行后的结果是一样的。
咦,那如果我们现在想让块级元素垂直居中呢,如何处理?
方法一: |
将元素设置为绝对定位 absolute,这样就可以让元素脱离普通文档流,且 absolute 有一特性:会将元素的 display 设置为 block。
然后,再设置绝对定位的坐标 (left,top,right,bottom) 为 0,这样会使浏览器为绝对定位包裹一层新的盒子模型。
再结合 margin,就可以你想水平居中 (margin:0 auto;) 就居中,垂直居中 (margin:auto 0;) 就居中了,水平垂直居中 (margin:auto;) 也完美。
下面列举的 demo 为‘水平垂直居中’:
<!DOCTYPE html> <head> <title>center</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style> .parent { width:50%; height:100px; border:1px solid black; position:relative; } .child { margin: auto; position: absolute; top:0; left:0; bottom:0; right:0; width:50px; height:50px; background:#22B14C; } </style> </head> <body> <div class="parent"> <div class="child"><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
</html>
PS:position:fixed 也可以脱离文档流,so 它和 absolute 是一样儿滴,区别就是 fixed 是相对于浏览器窗口进行定位的。
方法二: |
方法一是通过改变元素的文档流,那么除开改变它的文档流呢?
那我们就另辟蹊径,计算元素的宽高嘛。
么子意思?
以‘垂直居中’举例,倘若我们有个子元素 child,需要垂直居中于它的父元素 parent。如下:
图一
那么首先我们得将子元素 child 以父元素的顶点 (top,left=0 如上图所示),往下和右移动父元素宽高的 50%;如下图所示:
图二
再将子元素 Child 以 parent 中心点,往上和左移动自身元素宽高的 50%,就垂直居中啦,如下图所示:
图三
好了,这个流程我们是理清楚了,那用 CSS 应该怎么实现呢?
列举 2 个:
(1)、 margin + absolute
设置 child 为 absolute,将其 top、right 皆为 50%,那么就使得子元素层显上图图二的情况;
再将元素的 margin-top,margin-right 设置为 -50%,那么就可以实现垂直居中啦。
示例代码如下:
<!DOCTYPE html> <head> <title>center</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style> .parent { width:50%; height:100px; border:1px solid black; position:relative; } .child { position:absolute; width:50px; height:50px; top:50%; left:50%; margin-top:-25px; margin-left:-25px; background:#22B14C; } </style> </head> <body> <div class="parent"> <div class="child"><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
</html>
注:margin 的百分比值参照其包含块的宽度进行计算的。
另外默认浏览器一般默认 writing-mode:horizontal-tb 和 direction:ltr,即横向排版,所以 margin 无论宽高设置百分比时,都会以父元素的 width 进行计算。纵向嘛就是以父元素的 height 进行计算咯。
PS:如果你想纵向排版可以这么设置
#demo{
/*for browsers of wekit engine*/
-webkit-writing-mode: vertical-rl ;
/*for ie*/
writing-mode: tb-rl;
}
所以方法二中用 margin+absolute 让子元素居中时,margin 必须要知道子元素的宽高,切忌不能用百分比。
(2)、 translate + absolute
设置 child 为 absolute,将其 top、right 皆为 50%,那么就使得子元素层显上图图二的情况;
再通过 translate 将元素移动 50%,50%,也可以得到图三,实现垂直居中。
示例代码如下:
<!DOCTYPE html> <head> <title>center</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style> .parent { width:50%; height:100px; border:1px solid black; position:relative; } .child { position:absolute; width:50px; height:50px; top:50%; left:50%; <!-- 渐进增强 --> -webkit-transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%); transform: translate(-50%,-50%); background:#22B14C; } </style> </head> <body> <div class="parent"> <div class="child"><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
</html>
方法三: |
利用 table-cell 属性就可以轻松实现。
将父元素变为 table-cell,从而可以使用 table 的属性vertical-align:middle,使元素垂直居中,再将子元素 margin:0 atuo; 就可以实现水平居中咯。
PS:table-cell 必须包含在 display:table 元素中,table-cell 是属于 table 滴嘛。
示例代码如下:
<!DOCTYPE html> <head> <title>center</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style> .root { width:50%; height:100px; border:1px solid black; display:table; } .parent { display:table-cell; vertical-align:middle; } .child { width:50px; height:50px; background:#22B14C; margin:0 auto; } </style> </head> <body> <div class="root"> <div class="parent"> <div class="child"></div> </div> </div> </body> </html>
好了,css 之垂直水平居中就算完了 (弹性布局 Flex 不在本篇讨论范畴)。
晚安,everyone~