css 水平垂直居中的几种方法
水平垂直居中的几种方式
记录一下容器内只有单一元素时居中的几种方式
<div style="width: 300px; height: 300px" class="wrap">
<div style="width: 100px; height: 100px" class="box"></div>
</div>
1.容器flex,调整内部轴线
flex通过横竖两根轴线控制内部元素的分布位置
.wrap {
display: flex;
justify-content: center;
align-items: center;
}
2.flex + margin
设置父元素为flex时,margin会平均分配给内部的一个或多个元素,这时候在垂直方向就可以靠margin:auto来实现居中了,因为margin设置为auto时会平分空间
这篇文章原理讲的很好,还有很多实用的例子,通过设置margin来实现类flex布局
.wrap {
display: flex;
}
.box{
margin: auto;
}
3.容器grid,子元素margin-auto
.wrap {
display: grid;
}
.box{
margin: auto;
}
4.模拟table-cell
父设置为table-cell,子元素将被看成单元格td来处理,可以用vertical-align来实现居中
①vertical-align这个属性影响由inline-level(内联级)元素生成的盒子,这里子元素被视为td,变成了内联级,所以vertical-align产生了垂直居中的效果,正常情况下vertical-align不生效(注意不只是设置成内联级vertical-align就能生效,还取决于其他因素)
inline-level(内联级)元素包括:
- inline 内联元素一般是用来包裹文本的元素,比如span、strong、em标签等
- inline-block 内联-块元素(内嵌的块元素)可以在一行中排列显示,以具有width,height(也有可能是通过其内容确定的)和padding,border及margin。比如img、input标签等
- line-table(少见)
②这个属性还和baseline有关,比较深入的对vertical-align的理解可以看这篇文章或者这个,下面的方法5就是通过调整baseline实现的
vertical-align属性和line-height,baseline这两个属性联系非常紧密,最好能先理解这两个属性再用
.wrap {
display: table-cell;
text-align: center;
vertical-align: middle;
}
.box{
display: inline-block;
}
5.inline-block + vertical-middle
vertical-align默认对齐方式是以baseline对齐(vertical-align默认值为baseline)
几种不同情况下默认的baseline
- inline-block元素盒子里没有内容,是空盒子时,baseline位置就是该盒子margin-bottom的边界
- inline-block元素盒子里,有内容元素,并且overflow属性值为visible时(默认值),baseline位置就是该盒子最后一个内容元素的baseline
- inline-block元素盒子里,有内容元素,并且overflow属性值为非visible时 (比如overflow:hidden),那么该盒子的baseline位置就是该盒子margin-bottom的边界
vertical-align:middle的意思是与baseline值+x-height的一半(字母x高度的一半)对齐
可以看到baseline值+x-height的一半基本上是在中间
因此让父元素的line-height和height一样(line-height会自动调整行文本的高度),baseline+字母‘x’的一半高度这个值就变成了父元素的垂直方向的中点
子元素再vertical-align: middle,让子元素盒子垂直中点与父元素的baseline+字母‘x’高度的一半对齐,就可以垂直居中了(设置元素的vertical-align属性,并没有改变该元素的baseline位置,改变的只是与父元素基线对齐的位置)
.wrap {
text-align: center;
line-height: 300px;
}
.box{
display: inline-block;
vertical-align: middle;
}
但是如果高度不确定的情况下,line-height属性是不能设置100%的,不能写固定值,就需要改一下
可以增加一个不可见的div,把高度撑起来,后面相当于跟了一个文本节点,baseline+字母‘x’高度的一半变成了垂直方向的中心
参考这个
<div class="wrap" style="background: red;width: 300px;height: 300px">
<div class="box" style="background: blue;width: 100px;height: 100px"></div>
<span style="display:inline-block;height:100%;vertical-align:middle;font-size:0;"></span>
</div>
span是用来撑开高度的元素
另一种方法是通过css的before或after产生的伪元素利用height和vertical-align调整父元素的baseline位置来实现
伪元素的用法
<style>
.wrap {
text-align: center;
}
.wrap:after {
content: "";
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
.box {
display: inline-block;
vertical-align: middle;
}
</style>
子元素高度为什么能改变父元素baseline位置的具体原因
6.模拟grid
.wrap {
display: grid;
}
.box{
align-self: center;
justify-self: center;
}
7.margin + transform
margin设置为auto时会吸收可用的空间,比如如果想要居右,可以设置margin-left为auto,但是这种用法只能用在水平方向的布局,原因是页面的正常流程是自上而下阅读的,所以css规范中人为设定了margin:auto在垂直方向不生效,原因
浏览器:我都把上面渲染完了你告诉我这个要居中,上面的咋办?装没看见吧
垂直方向的居中用translate来实现
.wrap {
overflow: hidden;
}
.box{
margin: 50% auto;
transform: translateY(-50%);
}
8.比较简单的absolute + transform布局,父相对子绝对
父设置相对后可以保证子即使设置绝对,也会在父的内部,通过left和top先移动到父的中心点,然后子元素transform自己的-50%就能让父和子的中心点重合了
.wrap {
position: relative;
}
.box{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
9.absolute + margin-auto
如果元素设置为absolute布局,那么在水平和垂直方向上会遵守下面这个等式
left + margin-left + border-left + padding-left + content-width + padding-right + border-right + margin-right + right = 包含块元素的宽度(content-width)
简单说就是 边距 + margin + 边框 + padding + 宽度 = 总宽度
left,margin-left,content-width,margin-right,right 这5个属性可以设置为auto,auto条件下会吸收并平分可利用的空余空间
如果没有auto属性,那么会把空余空间都分配到right上
left、right、top、bottom这四个值优先级最高,如果不对这四个值进行设置,那么浏览器将会优先调整这个四个属性的值来满足上面的等式。(其实这里有个问题,官方文档中写的left、right、top、bottom这4个默认属性都是auto,但是在不设定的默认条件下这4个auto却没有平分剩余空间,目前还没有找到答案)
因此将这4个设置为0,就可以利用margin的auto,来实现平分空间,垂直水平都居中的效果
.wrap {
position: relative;
}
.box{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}