CSS 中,有几种经典的居中,水平居中,垂直居中。其中水平居中比较常见,也相对比较简单;垂直居中相对少见,但是也很见CSS 功底。
简单的水平居中
/* exp1 */
<style>
.ct {
background-color:gray;
height: 300px;
padding-top: 30px;
}
.content {
margin: 0 auto;
width: 300px;
height: 200px;
background-color:red;
}
</style>
<div class="ct">
<div class="content">宽 300px,高 200px,在页面水平居中</div>
</div>
简单的水平居中,只需在父元素的子元素中设置左右 margin 相等,由于父元素宽度可能不定,受 window resize
影响,因此不适合设置为固定值,一般设置为 上下 为 0
,左右为 auto
。
经典的垂直居中
垂直居中,两列等高,自适应宽度,是 CSS 的三大经典问题,特别是垂直居中,是布局中经常用到的一个方法,其方法有很多种。
- 伪元素对齐
此方法是利用 CSS 的vertical-align
属性,它可以指定元素在垂直方向上的对其方式,其值有:baseline
,top
,middle
,bottom
,text-top
,sub
等。但是次属性只对行内元素、表格单元格元素生效,无法用来对齐块级元素。因此,只能将元素的display
属性设置为inline-block
。
/* exp2 */
<div class="ct">
<div class="content">
<h1>这是标题</h1>
<p>这是内容,这段文字在当前区块内水平垂直居中</p>
</div>
</div>
<style>
.ct {
margin:0 auto;
width:500px;
height:300px;
text-align: center;
background-color:gray;
}
.ct::before {
content: '';
display:inline-block; // 行内元素
height: 100%;
vertical-align: middle;
}
.content {
display:inline-block; // 行内元素
vertical-align: middle;
}
</style>
上述代码中,设置了一个需要对其容器的元素,和一个伪元素,设置两者的display
属性为inline-block
,使得他可以使用vertical-align属性
,再设置两者对齐线为middle
,两者将对齐,而伪元素因为没有内容撑开宽度,因此不会显示。
- 绝对定位对齐
绝对定位的整体思路是子容器下沉垂直高度恰好为父容器高度的一半,再上浮自身高度的一半,达到垂直对齐的效果。
/* exp3 */
<div id="box">
<div id="child">This is child box</div>
</div>
/* exp4 */
#box {
width: 300px;
height: 300px;
background: #ddd;
position: relative;
}
#child {
background: orange;
position: absolute;
top: 50%; // 下沉父容器高度的一半
transform: translateY(-50%); // 上浮自身高度的一半
}
上述代码中,由于不知道子容器的高度值,因此设置transform
属性,其值为Y轴自身高度的一半translates(-50%)
,如果子元素的高度是固定值,则可以改为:
/* exp5 */
#child {
position: absolute;
width: 150px;
height: 100px;
top: 50%; // 下沉父容器高度的一半
margin-top: -50px; // 上浮自身高度的一半
}
上面代码中,因子元素高度为固定值,设置子元素高度为高度一半,如果子元素自身高度为相对值,也可以将其设置为一半:
/* exp6 */
#child {
position: absolute;
width: 150px;
height: 50%;
top: 50%; // 下沉父容器高度的一半
margin-top: -25%; // 上浮自身高度的一半
}
总结一下:
-
translate
属性是在无论子元素高度是否确定下都可以进行高度下沉的,设置translateY(-50%)
即为自身高度值的一半; - 而负
margin
方法上浮则是需要知道元素高度的相对值或者是绝对值,并将margin-top
设置为其一半。
另外,还可以借鉴水平居中里,左右margin
相等的思路,用绝对定位上下距离相等:
/* exp7 */
#child {
position: absolute;
width: 150px;
height: 100px;
top: 0;
bottom: 0;
margin: auto;
background-color: orange;
}
上面代码利用了水平对齐类似的margin: auto
的设置,因为上下的距离已经被设置成相等,即top: 0
,bottom: 0
;因此只需设置margin
为auto
就可以了。
- 父元素
padding
实现对齐
垂直居中无非是子元素上下边框与父元素上下边框距离相等,因此还可以利用父元素上下padding相等,实现子元素相对父元素垂直居中。
/* exp8 */
#parent {
border: 1px solid red;
padding: 50px 10px;
}
#child {
height: 20px;
border: 1px blue solid;
line-height: 100%;
text-align: center;
}
上面代码中,子元素高度设置为 20px
,父元素 padding
设置为上下 50px
,左右为 10px
,父容器没有设置固定宽度,全部由子元素撑开,因此父元素整体达到 content
高度为``120px`。
- 伪元素实现对齐
在整体原理(下沉父元素一半再上浮自身高度一半)不变的情况下,我们可以借助伪元素实现居中对齐。
/* exp9 */
#parent {
border: 1px red solid;
height: 250px;
width: 200px;
}
#parent::before {
height: 50%;
content: '';
display: block;
}
#child {
height: 90px;
background: #ccc;
transform: translateY(-50%);
}
上面代码中,设置了一个高度为父元素一半,但是无内容,不显示的伪元素#parent::before
,由于两者都是块级元素,按照文档流的排列,块级元素换行,需要排列的子元素上边框就位于父元素一半的位置,再上浮自身高度的一半,就实现了垂直居中。
总结一下:
- 整体思路1:子元素先下沉父元素高度的一半,再上浮自身高度一半,实现元素垂直居中。
- 下沉父元素高度的一半可以通过绝对定位(exp4/5/6) / 设置伪元素(exp9)等实现
- 上浮自身高度一般可以使用负
margin-top
实现(高度为固定值/确定值,如exp5/6);或者使用transform
属性设置为translateY(-50%)
实现(exp4)。
- 整体思路2:子元素上下边框与父元素上下边框高度相等
- 设置绝对定位,并且设置上下边框为距离相等(exp7)
- 设置父元素上下
padding
相等,并且撑满父元素(exp8)
- Flex 布局对齐
在 CSS3 提出 Flex 布局之后,问题变得简单许多。因为 Flex 布局本身就是针对就是针对弹性布局而设计的,因为越来越多的布局需要:
改变盒的大小,使得它们的结构保持固定
在 React Native 中,干脆就纯粹使用了 Flex 布局,而不再支持文档流。flex中垂直居中也变得非常简单。
/* exp10 */
#parent {
border: 1px red solid;
height: 250px;
width: 200px;
margin-left: 100px;
display: flex;
justify-content: center;
align-items: center;
}
#child {
height: 90px;
background: #ccc;
}
justify-content
和 align-items
属性分别是设置内部子元素主轴(默认为x轴从左到右)和交叉轴上(默认为y轴从上到下)的对齐方式,因此如果只需要垂直居中(y轴),只需设置align-items: center
就可以了。
类似的,如果将主轴设置为y轴,只需将 justify-content:center
就可以了。
/* exp11 */
#parent {
display: flex;
flex-direction: column;
justify-content: center;
}
- table 布局对齐
/* exp12 */
#parent {
width: 300px;
height: 300px;
background-color: #ddd;
display: table;
}
#child {
display: table-cell;
vertical-align: middle;
}
- Grid 布局
和 Flex 布局一样,Grid 布局浏览器支持程度较低,如果不考虑兼容问题,可以使用。
/* exp13 */
#box {
width: 300px;
height: 300px;
display: grid;
}
.two {
background: orange;
}
.one, .three {
background: skyblue;
}
参考阅读
- CSS垂直居中的12种实现方式,掘金用户:呆里呆气1
- CSS Flex排版:为什么垂直居中这么难?,winter。
- Aligning Items in a Flex Container,MDN 社区。