您的位置:首页 > Web前端 > CSS

解读 CSS 布局之水平垂直居中

2017-06-21 12:50 288 查看
对一个元素水平垂直居中,在我们的工作中是会经常遇到的,也是CSS布局中很重要的一部分,本文就来讲讲CSS水平垂直居中的一些方法。由于我们大搜车的日常工作中已经不再需要理会低版本IE,所以本文所贴出的方法,是没有去考虑IE的,如果有兼容需要,可以参见这篇文章: http://www.cnblogs.com/Dudy/p/4085292.html

先看一张图,这是去年cssConf大会时阿里的 @寒冬winter 老师放出来的:



如图所示,CSS布局是可以分为几大块的:
盒子内部的布局
文本的布局
盒模型本身的布局

盒子之间的布局visual formatting
脱离正常流normal flow的盒子的布局
absolute布局上下文下的布局
float布局上下文下的布局

正常流normal flow下的盒子的布局
BFC布局上下文下的布局
IFC布局上下文下的布局
FFC布局上下文下的布局
table布局上下文下的布局
css grid布局上下文下的布局

所有的CSS布局其实都是围绕着这些布局模块来的,水平垂直居中也一样。

一. 文本的水平垂直居中


line-height + text-align:center

DEMO链接

代码:
<div class='wrap'>
水平垂直居中水平垂直居中
</div>

html,body{
margin: 0;
}

.wrap{
line-height: 400px;
text-align:center;

height: 400px;
font-size: 36px;
background-color: #ccc;
}


这种方法只适合单行文字的水平垂直居中

二. 利用盒模型的水平垂直居中

我们一般讲的盒模型都是说的块级盒的盒模型,也只有块级盒的盒模型用得多一点,块级盒block-level box又是分别由content-box、padding-box、border-box、margin-box组成的,如下图:



也就说我任一个子盒子的水平和垂直方向的边与最外面盒子的间距都是可以控制的,因此也就有如下居中方法:


padding填充

DEMO链接

代码:
<div class="wrap">
<div class="content"></div>
</div>

@wrapWidth : 400px;

.wrap{
margin-left: auto;
margin-right: auto;
margin-top: 20px;
width: @wrapWidth;
height: @wrapWidth;
background-color: #ccc;
}

.content{
@contentWidth : 100px;
width: @contentWidth;
height: @contentWidth;
padding: (@wrapWidth - @contentWidth) / 2;
background-color: #333;
background-clip:content-box;
}


也可以用css3的calc()动态计算:

DEMO链接
<div class="wrap">
<div class="content"></div>
</div>

.wrap{
margin-top: 20px;
margin-left: auto;
margin-right: auto;
width: 400px;
height: 400px;
background-color: #ccc;
.content{
padding: -webkit-calc(~"(100% - 100px) / 2");
padding: calc(~"(100% - 100px) / 2");
width: 100px;
height: 100px;
background-color: #333;
background-clip: content-box;
}
}


注意这里我在calc中使用了一个~""的写法,这是less中的一个语法,告诉less这里不被less所编译,要是被less变异了的话,css的calc函数的参数就不是100% - 100px,而是0%了。


margin填充

DEMO链接

代码:
<div class="wrap">
<div class="ele"></div>
</div>

.wrap{
@wrapHeight : 400px;
@contenHeight : 100px;
overflow: hidden;
width: 100%;
height: @wrapHeight;
background-color: #ccc;
.ele{
margin-left: auto;
margin-right: auto;
margin-top: (@wrapHeight - @contenHeight) / 2;
width: 100px;
height: @contenHeight;
background-color: #333;
color: #fff;
}
}


使用margin填充我们需要知道元素的宽度,这点不太灵活,不过CSS3搞出了一个加fit-content的属性值,可以动态计算元素的宽度, DEMO链接

使用盒模型进行布局不会产生reflow,兼容也好,使用盒模型布局是一种布局思想,其实仅仅靠它就能实现很多visual formatting才能实现的布局,这是另一个话题,这里不展开。

三. absolute布局上下文下的水平垂直居中


50% + -50%

原理很简单,就是利用left:50%将盒子的左边先置于父容器的中点,然后再将盒子往左偏移盒子自身宽度的50%,这里有三种具体实现:

DEMO链接
<div class="wrap">
<div class="ele margin">水平垂直居中水平垂直<br>居中水平垂直居中水平<br>垂直居中水平垂直居<br>中水平垂直居中</div>
</div>

<div class="wrap">
<div class="ele translate">水平垂直居中水平垂直<br>居中水平垂直居中水平<br>垂直居中水平垂直居<br>中水平垂直居中</div>
</div>

<div class="wrap">
<div class="ele relative">
<div class="ele-inner">水平垂直居中水平垂直<br>居中水平垂直居中水平<br>垂直居中水平垂直居<br>中水平垂直居中</div>
</div>
</div>

.wrap{
position: relative;
width: 100%;
height: 200px;
border:1px solid;
background-color: #ccc;
.ele{
position: absolute;
left: 50%;
top: 50%;
background-color: #333;
&.margin{
width: 160px;
height: 100px;
margin-left: -80px;
margin-top: -50px;
}
&.translate{
-webkit-transform:translate3d(-50%, -50%, 0);
transform:translate3d(-50%, -50%, 0);
}
.ele-inner{
position: relative;
left: -50%;
top: -50%;
width: 100%;
height: 100%;
background-color: #333;
}
&.relative{
width: 150px;
height: 100px;
background-color: transparent;
}
}
}


上面三个方法中,margin方法和relative方法都需要知道元素的宽高才行(relative方法只知道高也行),适用于固定式布局,而transform方法则可以不知道元素宽高


text-align:center + absolute

text-aign:center本来是不能直接作用于absolute元素的,但是没有给其left等值的行级absolute元素是会受文本的影响的,可以参考张老师的 这篇文章

DEMO链接

代码:
<div class="wrap">
<div class="ele"></div>
</div>

.wrap{
text-align: center;

width: 100%;
height: 400px;
background-color: #ccc;
font-size: 0;
}
.ele{
position: absolute;
margin-left: -(100px / 2);
margin-top: (400px - 100px) / 2;

width: 100px;
height: 100px;
display: inline-block;
background-color: #333;
}


简单解释下,首先,text-align:center作用的是文本而不是absolute的元素,但是,当absolute元素为inline-block的时候,它会受到文本的影响,然后你可能会问这里没文本啊,我只能告诉你说这下面是有的,是个匿名的文本节点。具体的这里不展开,可以参考 标准 ,然后理解这句话:

If the inline box contains no glyphs at all, it is considered to contain a strut (an invisible glyph of zero width) with the A and D of the element's first available font

然后这个匿名文本由于受到text-align:center影响居中了,这个时候absolute盒子的左边跟父容器的中点对齐了,所以就还需要往回拉50%,这里用的是margin-left,你也可以用其它方式拉。然后就是垂直方向的对齐,垂直方向是不能被操作文本的属性影响的,所以我这里用的是margin-top来让它偏移下去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: