CSS 垂直居中
前沿
对元素进行垂直居中,虽然没有水平居中那么频繁,但也是很常用的操作,本章介绍垂直居中的方法。
如果你水平居中,能够完全理解,会发现这一节的原理和套路都是类似的,都是用一个类型的 CSS 属性,只是水平居中使用控制 X 轴的属性,而垂直居中使用控制 Y 轴的属性。
预储备知识
了解下面这些知识储备,可以更好的掌握本节的内容。
vertical-align 和 line-height 的关系
https://www.zhangxinxu.com/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height/
z-index 属性
用来设置定位元素的层叠顺序(仅仅只对定位元素有效)
取值可为正负整数,0
比较原则
- 如果是兄弟关系
- z-index 越大,层叠在越上面
- z-index 相等,写在后面的那个元素层叠在上面
- 如果不是兄弟关系
- 各自从元素自己以及祖先元素中,找出最邻近的 2 个定位元素进行比较
- 而且这 2 个定位元素必须有设置 z-index 的具体数值
清浮动的目的
让父元素计算总高度的时候,把浮动子元素的高度算进去
而清浮动的方式有很多,但大多都有各式各样的不足,这里只介绍一种个人认为最为成熟的方式
.container::after {
content: "";
display: block;
clear: both;
}
/* 为了适配以前的旧浏览器,还需要这么写 */
.container::after {
content: "";
display: block;
clear: both;
height: 0;
visibility: hidden;
}
这样做的好处是不会改变父元素格式,并且能够纯 CSS 样式解决,遵循结构与样式分离~
最后,介绍下 clear 属性
clear 的常用取值
- left:要求元素的顶部低于之前生成的所有左浮动元素的底部
- right:要求元素的顶部低于之前生成的所有右浮动元素的底部
- both:要求元素的顶部低于之前生成的所有浮动元素的底部
- none:默认值,无特殊要求
一般就只用在非浮动元素上,可以让非浮动元素与浮动元素不层叠。
height 和 line-height
- height
- line-height
设置父元素的 height
和 line-height
相等, 是一个万金油的操作,可以解决很多场景;无论是inline
元素,inline-block
元素,block
元素都可以。
line-height
的表现是通过 inline box 实现的,而无论 inline box 所占据的高度是多少(无论比文字大还是比文字小),其占据的空间都是与文字内容公用水平中垂线的。
操作 inline
元素
设置父元素的 height
和 line-height
相等。缺点是只能用于单行行内内容;要知道高度的值
例子如下:
<div style="
border: 1px solid #666;
height: 100px;
line-height: 100px;
">
<span>阿西河前端教程</span>
</div>
操作 inline-block
元素
设置父元素的 height
和 line-height
相等, 如:
<div style="
border: 1px solid #666;
height: 100px;
line-height: 100px;
">
<div style="border: 1px solid green;display: inline-block;">
阿西河
</div>
</div>
inline-block
元素是可以设置宽度和高度的,所以如果你有需要给子元素设置高度的需求,或者设置小于父级的背景或者下边框等,那么你需要子元素也设置height
和line-height
。
<div style="
border: 1px solid #666;
height: 100px;
line-height: 100px;
">
<div style="
background-color:#d4d4d4;
display: inline-block;
height: 50px;
line-height: 50px;
">
阿西河
</div>
</div>
利用“精灵元素”
利用精灵元素 (ghost element) 技术实现垂直居中,即在父容器内放一个 100% 高度的伪元素,让文本和伪元素垂直对齐,从而达到垂直居中的目的。
核心代码:
<div class="ghost-center">
<p>阿西河前端教程</p>
</div>
.ghost-center {
position: relative;
}
.ghost-center::before {
content: " ";
display: inline-block;
height: 100%;
width: 1%;
vertical-align: middle;
}
.ghost-center p {
display: inline-block;
vertical-align: middle;
width: 20rem;
}
操作 block 元素(定高)
设置 position:absolute
定位
设置子元素 position:absolute 并设置 top、bottom 为 0,
父元素要设置定位为 static 以外的值(如 relative),margin:auto;
如:
<div style="
border: 1px solid #666;
height: 100px;
position: relative;
">
<div style="
background-color:#d4d4d4;
height: 50px;
width: 150px;
position: absolute;
top: 0; bottom: 0;
margin: auto;
">
阿西河
</div>
</div>
利用 position
, top
和负 margin
- 设置元素为 absolute/relative/fixed
- margin= 负一半(可以是百分比的单位)
<div style="
border: 1px solid #666;
position: relative;
height: 100px;
">
<div style="
position: relative;
background-color:#d4d4d4;
height: 50px;
top: 50%;
margin-top: -25px;
">
阿西河
</div>
</div>
优点是适用于所有浏览器。
缺点父元素空间不够时,子元素可能不可见(当浏览器窗口缩小时,滚动条不出现时). 如果子元素设置了 overflow:auto, 则高度不够时,会出现滚动条。
calc
属性
介绍
这种方式原理和上面使用负margin-top
的原理输类似的,虽然没有用到margin-top
;
calc
是 CSS3 的属性
核心代码
position: absolute;
height:高度;
top: calc(50% - 一半的高度);
例子
<div style="
border: 1px solid #666;
position: absolute;
height:500px;
top: calc(50% - 250px);
">
阿西河前端教程
</div>
利用 position
和 top/bottom
和 margin: auto 0
- 1、position:absolute/relative/fixed
- 2、top/bottom:0
- 3、margin:auto
原理:当 top、bottom 为 0 时,margin-top&bottom 设置 auto 的话会无限延伸占满空间并且平分;脱离文档流
缺点:没有足够空间时,子元素会被截断,但不会有滚动条。
<div style="
border: 1px solid #666;
position: relative;
height: 100px;
">
<div style="
background-color:#d4d4d4;
position: absolute;
height: 50px;
top: 0;
bottom: 0;
margin: auto 0;
">
阿西河
</div>
</div>
操作 block 元素(不定高)
设置 padding-top
等于 padding-bottom
优点:兼容性非常好
缺点:如果父级的高度受到兄弟节点的影响,这样自己就不居中了
<div style="
border: 1px solid #666;
">
<div style="
padding-top: 20px;
padding-bottom: 20px;
">
阿西河
</div>
</div>
设置 display:table;
和 vertical-align
通过设置父元素 table
,子元素 table-cell
和 vertical-align
;
vertical-align:middle
的意思是把元素放在父元素的中部
缺点:设置 tabl-cell
的元素,宽度和高度的值设置百分比无效,需要给它的父元素设置 display: table
; 才生效;table-cell 不感知 margin,在父元素上设置 table-row 等属性,也会使其不感知 height;设置 float 或 position 会对默认布局造成破坏,可以考虑为之增加一个父 div 定义 float 等属性;内容溢出时会自动撑开父元素。
<div style="
border: 1px solid #666;
height: 100px;
display: table;
">
<div style="
display: table-cell;
vertical-align: middle;;
">
阿西河
</div>
</div>
设置 display:inline-block;和
vertical-align`
以前很流行的方法,也适应 IE7.
.parent::after, .son{
display:inline-block;
vertical-align:middle;
}
.parent::after{
content:'';
height:100%;
}
设置 flex
布局
在需要垂直居中的父元素上,设置 display:flex
和 align-items:center
要求:父元素必须显示设置 height 值
优点
- 内容块的宽高任意,优雅的溢出。
- 可用于更复杂高级的布局技术中。
<div style="
border: 1px solid #666;
height: 100px;
display: flex;
align-items: center;
">
<div>阿西河</div>
</div>
其它写法
#parent{
display: flex;
align-items: center;
}
或
#parent{display: flex;}
#son{align-self: center;}
或
/*原理:这个尚未搞清楚,应该是flex使margin上下边界无限延伸至剩余空间并平分了*/
#parent{display: flex;}
#son{margin: auto 0;}
任意个元素的写法
# parent{
display: flex;
align-items: center;
}
或
# parent{display: flex;}
.son{align-self: center;}
或
# parent{
display: flex;
flex-direction: column;
justify-content: center;
}
grid 属性
核心代码
display: grid;
例子
<div class="wp">
<div class="box">123123</div>
</div>
.wp {
display: grid;
}
.box {
align-self: center;
justify-self: center;
}
利用 position
和 top
和 transform
transform 中 translate 偏移的百分比就是相对于元素自身的尺寸而言的。
translate(0 -50%)
和translateY(-50%);
都可以。
<div style="
border: 1px solid #666;
height: 100px;
position: relative;
">
<div style="
position: absolute;
top: 50%;
transform: translate(0 -50%);
background-color:#d4d4d4;
">
阿西河
</div>
</div>
利用writing-mode
writing-mode 可以改变文字的显示方向,比如可以通过 writing-mode 让文字的显示变为垂直方向
<div class="wp">
<div class="wp-inner">
<div class="box">123123</div>
</div>
</div>
.wp {
writing-mode: vertical-lr;
text-align: center;
}
.wp-inner {
writing-mode: horizontal-tb;
display: inline-block;
text-align: center;
width: 100%;
}
.box {
display: inline-block;
margin: auto;
text-align: left;
}
使用 padding 实现子元素的垂直居中
这种实现方式非常简单,就是给父元素设置相等的上下内边距,则子元素自然是垂直居中的,当然这时候父元素是不能设置高度的,要让它自动被填充起来,除非设置了一个正好等于上内边距 + 子元素高度 + 下内边距的值,否则无法精确的垂直居中。
# box {
width: 300px;
background: #ddd;
padding: 100px 0;
}
# child {
width: 200px;
height: 100px;
background: #F7A750;
line-height: 50px;
}
设置第三方基准
这种方式也非常简单,首先设置一个高度等于父元素高度一半的第三方基准元素,那么此时该基准元素的底边线自然就是父元素纵向上的中分线,做完这些之后再给要垂直居中的元素设置一个 margin-top,值的大小是它自身高度的一半取负,则实现垂直居中。
<div id="box">
<div id="base"></div>
<div id="child">
Hello world,Hello world
</div>
</div>
# box {
width: 300px;
height: 300px;
background: #ddd;
}
# base {
height: 50%;
background: #AF9BD3;
}
# child {
height: 100px;
background: rgba(131, 224, 245, 0.6);
line-height: 50px;
margin-top: -50px;
}
使用 line-height 和 vertical-align 对图片进行垂直居中
<div id="box">
<img src="img/user.png">
</div>
# box{
width: 300px;
height: 300px;
background: #ddd;
line-height: 300px;
}
# box img {
vertical-align: middle;
}