把所有的东西都对齐吧 - 谈谈垂直居中的解决方案

"44年前我们就把人类送上了月球了,但现在我们仍然无法在css中实现垂直居中 -James Anderson"

难题

在CSS中对元素进行水平居中是非常简单的;如果是一个行内元素,就对父元素设置text-align:center;如果是一个它是一个块级元素,就对自身应用margin:auto.然而考虑到代码的DRY和较强的可维护性,如果要对一个元素进行垂直居中,可能是令人头皮发麻的一件事情了.

就这样在前端开发圈内看似及其常见的需求,从理论上似乎极其简单,在实践中,它往往难如登天,当涉及尺寸不固定的元素时尤为如此.

为了解决这一"绝世难题",于是前端开发者们殚精竭虑,脑洞大开,琢磨出了各种解决方案,大多数并不实用.

一路走来走了不少弯路,希望初入前端的小伙伴们可以走的更加通畅,总结分享给大家:

下面就让我们来探索现代css的强大威力:

基于表格布局法的解决方案

利用表格的显示模式,需要用到一些冗余的HTML元素

思路来源:

<table style="width:100%;height:100%;">
    <tr>
     <td style="text-align: center; vertical-align: middle;">
          Unknown stuff to be centered.
     </td>
  </tr>
</table>
html,body{
    height:100%;
}

摘自:https://css-tricks.com/centering-in-the-unknown/

我们发现在table中vertical-align: middle;实现了自动垂直居中.

基于曾经在网页早期风靡一时的表格布局法:实现了垂直居中

<div class="something-semantic">
   <div class="something-else-semantic">
       Unknown stuff to be centered.
   </div>
</div>
html,body {
  height:100%;
}
.something-semantic {
  display: table;
  width: 100%;
  height: 100%;
}
.something-else-semantic { 
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

但是由于表格布局法逐渐的退出舞台,这种方法也渐渐的不为所用

基于绝对定位的解决方案

早期实现垂直居中方法,要求具有固定的宽度和高度:

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

这种方法利用负外边距移动的方法,从而把元素放在视口的正中心.我们还可以借助强大的calc函数,省掉两行声明:

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

显然这个方法最大的局限性就是他要求元素具有固定宽度和高度.我们知道在通常情况下,固定宽度和高度的情况是极少的,对于那些需要居中的元素来说,其尺寸往往是由其内容决定的.如果能够找到一个属性的百分比以元素自身的宽高作为基准,那么难题就迎刃而解!遗憾的是,对于大多数的css属性(包括margin)来说,百分比都是以其父元素的尺寸为基准进行解析的.

css领域有一个很常见的现象,真正的解决方案往往来自我们最意想不到的地方:利用css变形属性,

当我们在进行translate()变形函数中使用百分比值时,是以这个元素位基准进行转换和移动的,而这正是我们所需要的.

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

从codepen中看到,利用css变形技巧,这个容器已经完美居中,满足我们的期望.

但是没有任何技巧十全十美,我们需要注意几点:

  • 我们有时不能选择绝对定位,他对整个布局影响太过强烈
  • 如果需要居中的元素已经在高度上超过了视口,那它的顶部部分就会被视口裁掉
  • 在某些浏览器中,这个方法可能会导致元素的显示模糊,因为元素可能会被放置在半个元素上.可以用一个偏hack的手段来修复transform-style:preserve-3d

基于视口的解决方案

假设我们不使用绝对定位,仍然采用translate()技巧来把这个元素以其自身宽高的一半为距离进行移动;但是在缺少left和top的情况下,如何吧这个元素放在容器正中心呢?

我们的第一反应很可能用margin属性的百分比值来实现,就像这样:

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

但是却产生了十分离谱的效果.原因在于margin的百分比值是以父元素的宽度作为解析基准的

在CSS值与单位(第三版)定义了一套新的单位,称为视口相关的长度单位

  • vm是与视口宽度相关的.1vm相当于视口的1%
  • 与vw类似,1vh相当于视口的1%
  • 当视口宽度小于高度时,1vmin等于1vw,否则等于1vh
  • 当视口宽度大于高度时,1vmax等于1vw,否则等于1vh

在这个例子中,我们适用外边距的是vh单位

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

我们可以看到,其效果堪称完美.这个技巧更适合于在视口中居中的场景.

基于Flexbox的解决方案

这是毋庸置疑的最佳解决方案,因为Flexbox(伸缩盒)是专门针对这类需求所设计的.现代浏览器对于Flexbox支持度已经相当不错了

我们只需要两行声明即可:先给这个待定居中元素的父元素设置display:flex(在使用的例子中是body元素),在给这个元素设置我们在熟悉不过的margin:auto

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

Flexbox还有一个好处就是,它可以将匿名容器(即使没有节点包裹的文本节点)垂直居中.

<main>center me,place!</main>

借助Flexbox规范所吸引人的align-itemsjustify-content属性,我们可以让它内部文本也实现居中

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

把所有的东西都对齐吧!

根据盒对齐模型(第三版)的计划,在未来,对于简单的垂直居中的要求,我们完全不需要动用特殊的布局模式.我们只需要这行代码就可以搞定

align-self:center;

不知不觉间,我们身边的浏览器都开始让它成为现实(但是路途还很遥远:IE10及更早版本不支持,Safari 7.0 及更早版本使用-webkit前缀)

原文地址:http://www.chenqaq.com/2017/12/07/css-verticalMiddle/

参考

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏黒之染开发日记

【easeljs】矢量形状 Shape类

一个Shape(形状)允许你在显示列表中显示矢量图。它包含一个带有所有绘制矢量图形的方法的Graphics(图形)实例。Graphics实例可以在多个Shape...

613
来自专栏互联网杂技

css负边距之详解

自从1998年CSS2作为推荐以来,表格的使用渐渐退去,成为历史。正因为此,从那以后CSS布局成为了优雅代码的代名词。 对于所有设计师使用过的CSS概念,负边距...

3248
来自专栏云时之间

NLP系列学习:数据平滑

各位小伙伴们大家好,数据平滑这个地方我想使用宗成庆老师的书中的一个例子进行开始,从而引出这一篇文章的主题,我们为什么要需要数据平滑以及常用的数据平滑的模型,话不...

2757
来自专栏程序员互动联盟

【专业技术】图像格式转化规律探秘

存在问题: 搞视频编解码的童鞋对此深刻理解,但是好多小伙伴在andriod或其他嵌入上做启动动画时候图像是如何转化存在一定的疑惑。 解决方案: 针对这些问题我们...

3326
来自专栏YoungGy

MMD_3a_CommunitiesInSN

SN means social network。 概述 实例 需要解决的问题 从AGM到Network 模型 特点 从AGM到bigClam bigClam的求...

2039
来自专栏Coding迪斯尼

用深度学习实现自然语言处理:word embedding,单词向量化

前几年,腾讯新闻曾发出一片具有爆炸性的文章。并不是文章的内容有什么新奇之处,而是文章的作者与众不同,写文章的不是人,而是网络机器人,或者说是人工智能,是算法通过...

571
来自专栏人工智能LeadAI

使用CNN+ Auto-Encoder 实现无监督Sentence Embedding (代码基于Tensorflow)

1前言 这篇文章会利用到上一篇: 基于Spark /Tensorflow使用CNN处理NLP的尝试的数据预处理部分,也就是如何将任意一段长度的话表征为一个2维数...

3284
来自专栏开心的学习之路

知识篇——聚类算法应用

时隔两月开始继续储备机器学习的知识,监督学习已经告一段落,非监督学习从聚类开始。 非监督学习与监督学习最大的区别在于目标变量事先不存在,也就是说 监督学习...

3065
来自专栏人工智能

基于TensorFlow的循环神经网络生成矢量格式的伪造汉字

注意:对于中文汉字和日文汉字我根据具体情况交替使用它们。

7168
来自专栏机器之心

CVPR 2018 | UNC&amp;Adobe提出模块化注意力模型MAttNet,解决指示表达的理解问题

3019

扫码关注云+社区