文档章节

CSS垂直居中

WolfX
 WolfX
发布于 2016/04/25 11:43
字数 1877
阅读 58
收藏 5

44年前我们把人送上月球,但在CSS中我们仍然不能很好实现垂直居中——@James Anderson

让一个元素水平居中对于CSS来说非常简单:如果是一个内联元素,我们可以在他的父元素上设置text-align:center;;如果是一个块元素,我们可以使用margin:auto;。然而,只要一想到让一个元素垂直居中,让人死的心都有了。

多年来,垂直居中已成为CSS的不朽神话,也是前端专业人士群体中的一个内部笑话。原因是:

  1. 经常需要使用
  2. 理论上看上去非常简单
  3. 过去实战中要实现是极其困难,特别是元素大小固定时

前端开发人员多年来尽所能的来解决这个问题,共中最令人不安的是使用了很多Hack手段。在这一节中,我们一起探索一些实现垂直居中现代技术。注意,有一些受欢迎的技术,不在这里讨论,主要是因为:

  1. 表格布局不讨论(表格显示模式),因为它需要一些冗余的HTML标签
  2. inline-block方法不包括,因为要使用很多Hack手段

然而,如果你对这方面感兴趣,你可以阅读Chris Coyier写的博文《Centering in the Unknown》,里面介绍了这两种技术。

如果没有特殊声明,后面示例用的HTML结构都是在<body>元素中插入下面的标签:

<main>
    <h1>Am I centered yet?</h1>
    <p>Center me, please!</p>
</main>

为了得到下图所示效果,我们也应用一些基本的CSS样式,比如background、padding等等:

绝对定位解决方案

最早实现垂直居中的技术是元素需要一个固定的宽度和高度:

main {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -3em; /* 6/2 = 3 */
    margin-left: -9em; /* 18/2 = 9 */
    width: 18em;
    height: 6em;
}

从本质上讲,它将元素的左上角点移到视窗中心点,然后使用负的margin(使用margin-top和margin-left),而且margin的值是元素宽度和高度的一半,使元素的中心点与视窗的中心点重合。如果使用calc()可以减少两个样式:

main {
  position: absolute;
  top: calc(50% - 3em);
  left: calc(50% - 9em);
  width: 18em;
  height: 6em;
}

显然,这种方法最大的问题是,元素需要一个固定的尺寸,而需要垂直居中元素的尺寸常常是需要由它的内容来决定。如果我们有办法使用百分比来控制元素尺寸,我们的问题就解决了。不幸的是,对于大多数CSS属性(包括margin)百分比的值是相对于其父元素的宽度来决定。

在CSS中常常可以看到很多解决方案是不可思议。在这个例中,就可以使用CSS3的transform。可以在transform中的translate()使用百分比,让元素移动是相对于自身的宽度和高度,这种方案正是我们需要的。

main {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

当然,没有哪门技术是完美的,在实际使用中要注意一下以下几个事项:

  1. 绝对定位通常不是一个很好的选择,因为它对整体的布局影响相当的大。
  2. 如果垂直居中元素的内容比视窗高度更高的话,它的顶部会被裁剪掉,如下图所示。但是这个问题可以解决,只不过需要使用一些Hack手段。
  3. 在一些浏览器中,可能会导致元素出现略微的模糊,那是因为元素有可能被放置在半个像素位置上。我们可以通过transform-style:preserve-3d来解决,尽管这是一个Hack手段,不能保证它不会过时。

视窗单位的解决方案

如果想避免使用绝对定位,我们仍然可以使用translate()方法,其值刚好是元宽度和高度的一半。然而,我们如何不使用top和left将元素从top和left移动50%的偏移量呢?

首先想到的是给margin属性一个百分数,像这样:

main {
    width: 18em;
    padding: 1em 1.5em;
    margin: 50% auto 0;
    transform: translateY(-50%);
}

然而,正如你所看到的效果,如下图所示:

这产生了非常奇怪的效果。主要原因是margin的百分比计算是相对于父容器的width来计算。是这样的,甚至包括margin-top和margin-bottom。

值得庆幸的是,如果我们想让元素在视窗中居中,还是有希望的。CSS Values and Units Level 3定义了一种新的单位,称为相对视窗(viewport-relative)长度单位。

  1. vw是相对于视窗的宽度。与你预期刚好相反,1vw相当于视窗宽度的1%,而不是100%
  2. 与vw相似的是,1vh相当于视窗高度的1%
  3. 如果视窗的宽度小于高度,1vmin等于1vw,反之,如果视窗宽度大于高度,1vmin等于1vh
  4. 如果视窗的宽度大于高度,1vmax等于1vw,反之,如果视窗宽度小于高度,1vmax等于1vh

在这个示例中,我们需要给margin的值设置vh单位:

main {
    width: 18em;
    padding: 1em 1.5em;
    margin: 50vh auto 0;
    transform: translateY(-50%);
}

正如你看到效果很完美。

当然,这种方法有用性是有极限的,因为它只适用于元素在视窗中垂直居中。

请注意,还可以使用相对视窗单位来创建全屏效果,而且不需要使用任何脚本。更多细节可以阅读Andrew Ckor写的《Make full screen sections with 1 line of CSS》博文。

Flexbox的解决方案

这无疑是最好的解决方案,因Flexbox的出现就是为了解决这样的问题。其他解决方案仍然可用,唯一原因是他们能更好的在浏览器上呈现,不过Flexbox在现代浏览器也得到更好的好支持。

只需要两个样式,在需要垂直居中的父元素上设置display:flex(这个示例中就是<body>)和在垂直居中的元素上设置margin:auto(这个示例中就是<main>):

body {
    display: flex;
    min-height: 100vh;
    margin: 0; 
}
main {
    margin: auto;
}

注意,当使用Flexbox和margin:auto时,元素不仅水平居中,而且也会垂直居中。也注意,我们甚至没有设置宽度(如果我们想要也可以设置),其实指定的宽度相当于max-content。

如果浏览器不支持Flexbox,那么结果看起来就会像下图(如果我们给元素设置了宽度):

即使不是垂直居中,还是可以接受的。

Flexbox的另一个优点是,可以让匿名容器垂直居中。例如,我们将结构换成:

<main>Center me, please!</main>

我们可以通过align-items和justify-content属性使设置固定尺寸的<main>容器里面的文本居中。如下图所示:

我们可以在<body>和需要居中的元素<main>使用相同的属性,同时使用margin:auto做为备用,以于优雅降级。

main {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18em;
    height: 10em;
}

新特性:对齐所有东西

CSS Box Alignment Level 3已经在计划,在未来我们甚至不需要使用不同的布局模式就能非常容易的实现垂直居中,我们只需要像下面这样做:

align-self: center;

不管元素上使用其他样式,这个将来都能运行。这听起来令人难以置信,但将来在浏览器中是可以渲染的。

本文转载自:http://www.w3cplus.com/css3/css-secrets/vertical-centering.html

共有 人打赏支持
WolfX

WolfX

粉丝 52
博文 246
码字总数 31477
作品 0
南京
技术主管
探究 HTML元素的水平垂直居中

HTML: <body> <div class="maxbox"> <div class="minbox align-center"></div> </div></body> 父元素 .maxbox{ position: relative; width: 500px; height: 500px; margin: 5px; box-shado......

我输过但从未怕过
2016/03/04
19
0
如何让DIV水平和垂直居中

我们在设计页面的时候,经常要把DIV居中显示,而且是相对页面窗口水平和垂直方向居中显示,如让登录窗口居中显示。我们传统解决的办法是用纯CSS来让DIV居中。在本文中,我将给大家讲述如何用...

ForingY
2016/06/26
11
0
如何让div中的内容垂直居中

虽然Div布局已经基本上取代了表格布局,但表格布局和Div布局仍然各有千秋,互有长处。比如表格布局中的垂直居中就是Div布局的一大弱项,不过好在千变万化的CSS可以灵活运用,可以制作出准垂直...

文文1
2015/09/21
25.5K
0
[译文]CSS的水平/垂直居中:一篇完整的指南

原文:Centering in CSS: A Complete Guide 在CSS中居中是(开发者)抱怨CSS设计的代表问题之一。有人嘲笑说:这有什么困难的呢?我认为,难度不在于解决问题,而在于有如此多的不同解决方法...

huangpin815
2017/09/26
0
0
元素水平居中和垂直居中的几种简单方法

一、如何使元素在水平方向上居中 1. 使用text-align:center。 在父级元素的CSS样式设置text-align:center。把内部嵌套一个div把它当作文本来对待,不过这个方法有时候是不管用的。 2.在需要居...

小陈同学
2014/05/07
0
3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Confluence 6 删除垃圾内容

属性(profile)垃圾 属性垃圾的定义为,一个垃圾用户在 Confluence 创建了用户,但是这个用户在自己的属性页面中添加了垃圾 URL。 如果你有很多垃圾用户在你的系统中创建了属性,你可以使用...

honeymose
今天
0
0
qduoj~前端~二次开发~打包docker镜像并上传到阿里云容器镜像仓库

上一篇文章https://my.oschina.net/finchxu/blog/1930017记录了怎么在本地修改前端,现在我要把我的修改添加到部署到本地的前端的docker容器中,然后打包这个容器成为一个本地镜像,然后把这...

虚拟世界的懒猫
今天
1
0
UML中 的各种符号含义

Class Notation A class notation consists of three parts: Class Name The name of the class appears in the first partition. Class Attributes Attributes are shown in the second par......

hutaishi
今天
1
0
20180818 上课截图

小丑鱼00
今天
1
0
Springsecurity之SecurityContextHolderStrategy

注:下面分析的版本是spring-security-4.2.x,源码的github地址是: https://github.com/spring-projects/spring-security/tree/4.2.x 先上一张图: 图1 SecurityContextHolderStrategy的三个......

汉斯-冯-拉特
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部