水平垂直居中的17种方法
面试的时候,绝不能只说一种,绝不能说一种解决方案,绝不能停下你吞吞吐吐的嘴
CSS 方面问的最多的问题之一,我想分三种情况,水平居中、垂直居中和水平垂直居中来分析
单单就水平垂直居中而言,大概有以下几种方案:
居中元素不定宽高
- absolute + transform
- flex 属性居中
- flex + 子项 margin auto
- grid 属性居中
- grid + 子项 margin auto
- grid + 子项属性居中
- -webkit-box 属性居中
- table-cell + text-align
- line-height + text-align
- writing-mode
- table
仅居中元素定宽高适用:
- 须知宽高 + absolute + 负 margin
- 须知宽高 + absolute + calc
- 须知宽高 + absolute + margin auto
局限性较大的全局居中
- 须知宽高 + fixed + transform
- 须知宽高 + fixed + 负 margin
- 须知宽高 + fixed + calc
- 须知宽高 + fixed + margin auto
水平居中
text-align: center
1 | text-align: center; |
需设置 display: inline-block
行内块元素
绝对定位 + transform 位移
1 | position: absolute; |
脱离文档流
宽度+ margin: 0 auto
1 | width: 100px; |
这里说明下,width:100px
必须是具体的数字,且这个居中是外层居中,宽度中的内容没有居中
垂直居中
绝对定位 + transform 位移
1 | position: absolute; |
与水平方向的居中一样,都是脱离文档流的做法
table-cell + vertical-align
1 | display: table-cell; |
display: table-cell
,让其标签元素以表格单元格的形式呈现,类似于 td
标签,
vertical-align: middle
,用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直居中
水平垂直居中
绝对居中 + transform 位移
1 | <div class="father"> |
1 | .father { |
flex 属性居中
1 | <div class="father"> |
1 | .father { |
flex + margin auto
1 | <div class="father"> |
1 | .father { |
grid 属性居中
1 | <div class="father">123123</div> |
1 | .father { |
grid 子项属性居中
1 | <div class="father"> |
1 | .father { |
grid + margin auto
1 | <div class="father"> |
1 | .father { |
grid 和 flex 很像,是 flex 的升级版,所以 grid 能做的事情更多
以上绝对定位、flex、grid 关于水平垂直居中的做法,剩下再说居中比较老的布局方法
-webkit-box 属性居中
这是一个已经过时的布局,可以看看这篇文章 CSS3 display: flex 和 display: box 有什么区别?
网友一丝说:
flex 是 2012 年的语法,是以后的标准
box 是 2009 年的语法,已经过时,需要加上对应前缀
1 | <div class="father"> |
1 | .father { |
table-cell + text-align
1 | <div class="father"> |
1 | .father { |
line-height + text-align
1 | <div class="father"> |
1 | .father { |
line-height
与 height
,行高和高度一样高,自然就垂直方向居中了
writing-mode
1 | <div class="father"> |
1 | .father { |
这个很冷闷,有人介绍过这种情况
table
1 | <table> |
1 | .father { |
table 标签自己将它垂直居中了,text-align:center
后就是水平居中了
可以看 demo
当元素有宽高的情况,又多了三种方案
须知宽高 + 绝对居中 + margin 负边距
1 | <div class="father"> |
1 | .father { |
父元素必须要有个高度,这样才能撑开容器。子元素必须要有个宽高,才能计算出 margin 值
须知宽高 + 绝对定位 + calc
1 | <div class="father"> |
1 | .father { |
与 margin 负边距一个道理,父元素需要设置一个高度。子元素必须要有高度,不用 margin,而用 CSS3 中的 calc,计算出要居中位移,兼容性需要支持 CSS3 属性
须知宽高 + 绝对居中 + margin: auto
1 | <div class="father"> |
1 | .father { |
同以上两种情况。
这三种需要定位方式来实现水平垂直居中的方法,需要设置父元素的高度(一定要有,撑开画面),子元素需要设置宽高,前两种方法是为了算出它在父元素中的相对位置,后一种方法是为了说明子元素是个容器(如果不设置宽高,就是无)
其他方法
其实,水平垂直居中方面,如果面试官硬要问还有吗?还真的有,用 fixed 定位。但这个方法有缺陷,虽然能实现水平垂直居中,但它是相对于视口(viewport),而非父元素
方法就是以上用 absolute 实现的改成 fixed 即可
- 须知宽高 + fixed + transform
- 须知宽高 + fixed + 负 margin
- 须知宽高 + fixed + calc
- 须知宽高 + fixed + margin auto
这四种方法,都需要设置子元素的宽高
这里贴一下代码
1 | <div class="father"> |
1 | /* transform */ |
总结
随着微软宣布放弃 IE11,现实项目中完全可以使用 flex 布局,grid 部分还不适配,但是以后肯定会取代 flex。
虽然写了很多,但是自己工作中也不会使用 table 、writing-mode、-webkit-box 等过时的布局方式,写这篇文章,纯粹是为了面试时被问到这种问题。
收获是 absolute 的居中要父子同心(父元素设置高度,子元素设置宽高),fixed 的居中只需要设置子元素的宽高。
线上 demo 查看