在CSS中水平居中一个元素非常简单:如果它是一个内联元素,应用text-align:center到它的父元素;如果它是块级元素,只需将margin:auto应用于自身。但是,如果你想让一个元素垂直居中,可能光想想就头皮发麻。长期以来,为了解决这个绝世难题,前端开发者苦苦思索,想出了各种解决方案,可惜大多都不实用。在本指南中,我们将探索现代CSS的强大力量,并用一种??新的思路来克服各种场景下的垂直居中问题。请注意,有几种技术非常流行,但这里不会深入探讨,原因如下:表格布局方法(使用表格显示模式)需要使用一些冗余的HTML元素,不够优雅和简单实现,所以这里不多介绍。inlineblock的方法也不讨论了,因为在我看来,这个方法很hack。如果您有兴趣,请查看ChrisCoyier所著的《以未知为中心》。这篇优秀的文章详细介绍了这两种技术。我们将使用以下结构代码,直接插入到
元素中(但实际上我们将探索的技巧与容器无关):
AmIcenteredyet?
请让我居中!
我居中了吗?请让我居中!image基于绝对定位我们先来看一个早期的垂直居中方法,它要求元素具有固定的宽度和高度:main{位置:绝对;顶部:50%;左:50%;保证金顶部:-3em;/*6/2=3*/margin-left:-9em;/*18/2=9*/width:18em;height:6em;}这段代码基本上做了几件事:首先将这个元素的左上角放在视口的中心(或者最近的具有定位属性的祖先元素)然后使用Negativemargins将其向左和向上移动(距离等于其宽度和高度的一半),从而将元素的准确中心放置在视口的准确中心。借助强大的calc()函数,这段代码还可以省去两个声明:main{position:absolute;顶部:计算(50%-3em);左:计算(50%-9em);宽度:18em;height:6em;}显然,这种方法最大的局限性在于它要求元素的宽高是固定的。一般来说,对于那些需要居中的元素,其大小往往由其内容决定。如果我们能够根据元素本身的宽高找到一个属性的百分比值,那么我们的问题就迎刃而解了!不幸的是,对于大多数CSS属性(包括margin),百分比是相对于其父元素的大小来解析的。真正的解决方案通常来自我们最意想不到的地方,这是CSS世界中的普遍现象。在这种情况下,答案来自CSSTransforms。当我们在translate()转换函数中使用百分比值时,根据元素本身的宽高进行转换和移动,这正是我们所需要的。接下来,您不需要在偏移量中硬编码元素的大小,只要您使用基于百分比的CSS转换来偏移元素即可。这样,我们就可以完全去掉对固定大小的依赖:main{position:absolute;顶部:50%;左:50%;transform:translate(-50%,-50%);}可以看到,这个容器完美的居中了,完全达到了我们的预期。image当然,没有一种技术是完美的,上述方法也有一些需要注意的地方:有时我们不能使用绝对定位,因为它对整个布局的影响太强了。如果要居中的元素的高度已经超过视口,则其顶部将被视口剪裁。有办法解决这个问题,但黑客太强大了。在某些浏览器中,这种方法可能会导致元素的显示有些模糊,因为元素可能被放置在半个像素上。这个问题可以用transform-style:preserve-3d修复,但是这个修复也可以算是hack,很难保证以后不会出问题。图片在线示例:http://dabblet.com/gist/cd12f...基于viewport,假设我们不想使用绝对定位,我们仍然可以使用translate()技术来移动这个元素其宽度和高度的一半的距离;但是在没有left和top的情况下,如何将这个元素的左上角放在容器的中央呢?我们的第一反应大概是使用margin属性的百分比值,像这样:main{width:18em;padding:1em1.5em;margin:50%auto0;transform:translateY(-50%);}然而,如图所示,这段代码会产生非常离谱的结果:image原因是margin的百分比值分辨率是基于父元素的宽度。没错,即使对于margin-top和margin-bottom也是如此!不过,幸运的是,如果您只想将元素相对于视口居中,那还是有希望的。CSSValuesandUnitsModuleLevel3定义了一组新的单位,称为与视口相关的长度单位。vw:视口宽度的1%vh:视口高度的1%vmin:视口较小尺寸的1%vmax:视口较大尺寸的1%在我们的例子中,应用于边距的vh单位:main{width:18em;padding:1em1.5em;边距:50vhauto0;transform:translateY(-50%);}可以看到,效果很完美。当然,这个技巧的用处相当有限,因为它只适用于视口居中的场景。image在线示例:http://dabblet.com/gist/bf12b...基于Flexbox,这无疑是最好的解决方案,因为Flexbox就是专门为这种需求设计的。我们讨论其他选项只是因为浏览器对它们的支持稍好一些。但实际上,目前现代浏览器对Flexbox的支持还是相当不错的。我们只需要写两行声明:首先为要居中的元素的父元素(在本例中为元素)设置display:flex,然后为元素本身设置熟悉的margin:auto(在在此示例中,它是
元素):body{display:flex;min-height:100vh;margin:0;}main{margin:auto;}请注意,当我们使用Flexbox时,margin:auto不仅在水平方向居中元素,也在垂直方向居中。此外,我们甚至不需要指定任何宽度(当然,如果我们愿意,我们可以):居中元素的宽度等于max-content。如果浏览器不支持Flexbox,页面渲染结果看起来和我们的起点图像一样(如果设置了宽度)。虽然没有垂直居中的效果,但是完全可以接受。Flexbox的另一个好处是它还可以垂直居中匿名容器(即没有被标签包裹的文本节点)。例如,假设我们的结构代码是:JavaScriptCenterme,please!1Centerme,please!我们先给主元素分配一个固定大小,然后用借助Flexbox规范引入的align-items和justify-content属性,我们还可以将其中的文本居中:main{display:flex;align-items:center;证明内容:居中;宽度:18em;高度:10em;}图片