在css中对元素进行水平居中是非常简单的:如果它是一个行内元素,就对它的父元素应用text-align:center
;如果是一个块级元素,就对自身应用margin:auto;
。
而如果要对一个元素垂直居中,可能光是想想就令人头皮发麻了。
在本篇中,我们将探索现代css的强大威力,以全新的思路去攻克各种场景下的垂直居中难题。
我们将使用如下所示的结构代码,并直接插入<body>
元素中(实际上我们探讨的技巧与容器无关)。
|
|
我们将设置一些基本样式,如下所示:
得到这样的一个效果,[点此预览demo]
1.基于绝对定位的解决方案
我们先来看一个早期的垂直居中方法,它要求元素具有固定的宽度和高度。
这段代码在本质上做了这样几件事:先把这个元素的左上角放置在视口(或最近的,具有定位属性的祖先元素)的正中心,
然后再利用负外边距把它向左、向上移动(移动的距离相当于它自身宽高的一半),从而把元素的正中心放置在视口的正中心。
显然,这个方法最大的局限在于它要求元素的宽高是固定的。
2.利用css变形技巧
当我们在translate()
变形函数中使用百分比值时,是以这个元素自身的宽度和高度为基准进行换算和移动,运用这一点,我们可以彻底解除对固定尺寸的依赖。
利用这个技巧,可以让宽高不固定的元素垂直居中。
当然,上面这个方法也有一些需要注意的地方。
-我们有时不能选用绝对定位,因为它对整个布局的影响太过强烈。
-如果需要居中的元素已经在高度超过视口,那它的顶部会被视口切掉,有一些办法可以绕过这个问题,但是hack味道过重。
-在某些浏览器中,显示有些模糊,因为可能被放置在半个像素上,可以用transform-style:preserve-3d
来修复,不过这个修复手段也可以认为是一个hack,难保在未来不会出问题。
3.基于视口单位的解决方案
假设我们不想使用绝对定位,仍然可以采用translate()
技巧来把这个元素以其自身宽高的一半为距离进行移动;但在缺少left和top的情况下,如何把这个元素的左上角放置在容器的正中心呢?
第一反应是用margin属性的百分比值来实现,就像这样:
不过这段代码会产生十分离谱的结果,点击demo
原因在于margin的百分比值是以父元素的宽度作为解析基准的。
我们期望margin的百分比值可以基于视口的尺寸来解析,但实际是行不通的。
不过幸运的是,如果只是想把元素相对于视口进行居中,仍然是有希望的。css值与单位定义了一套新的单位,称为视口相关的长度单位。
-vw是与视口宽度相关的,与常人的直觉不符的是,1vw实际上表示视口宽度的1%,
-与vw相似,1vh表示视口高度的1%
-当视口宽度小于高度时,1vmin等于1vw,否则等于1vh
-当视口宽度大于高度时,1vmax等于1vw,否则等于1vh
所以我们可以这么做:
当然这个技巧的实用性是相当有限的,只适用于在视口中居中的场景。
4.基于flexbox的解决方案
这毋庸置疑是最佳解决方案,我们探讨其他方案,仅仅是因为那些方案在浏览器的支持程度上稍微好一些,其实目前现代浏览器对flexbox的支持度已经相当不错了。
我们只需写两行声明即可:
先给这个待居中的父元素设置display:flex;
(这个例子中是
再给这个元素自身设置
margin:auto
(这个例子中是
|
|
当我们使用flexbox
时,margin:auto
不仅在水平方向上将元素居中,垂直方向上也是如此。
还有一点,我们不需要设置任何宽度,(当然,如果需要,也可以指定。):这个居中元素分配到的宽度等于max-content。
如果浏览器不支持flexbox,页面就和起点图一样,虽然没有垂直居中,但完全可以接受。
flexbox的另一个好处在于,它可以将匿名容器(即没有被标签包裹的文本节点)垂直居中。例如:
html代码
我们可以借助flexbox规范引入的align-items和justify-content属性,让它内部的文本也实现居中。
使用table
该方法我们不再探讨
使用table-cell居中
上面说得table在现在来说有点过时,但我们仍然可以把一个div元素通过display:table;
把它模拟成一个表格。
html代码
css样式
|
|
关于未来
根据盒对齐模型(第三版)的计划,在未来,对于简单的垂直居中需要,我们完全不需要动用特殊的布局模式了,因为只需要下面这行代码就可以搞定:
参考链接:
原文来自《css揭秘》这本书。
table布局:Centering in the Unknown