专栏首页前端布道CSS实现元素居中原理解析

CSS实现元素居中原理解析

在 CSS 中要设置元素水平垂直居中是一个非常常见的需求了。但就是这样一个从理论上来看似乎实现起来极其简单的,在实践中,它往往难住了很多人。

让元素水平居中相对比较简单:如果它是一个行内元素,就对它的父元素应用 text-align: center;如果它是一个块级元素,就对它自身应用 margin: auto

然而如果要对一个元素进行垂直居中,那就没有那么容易了,有时候光是想想就令人头皮发麻了。

本文分别从行内元素和块级元素进行说明,将目前比较流行的实现方式进行汇集并解析实现原理,方便大家查阅。这里要说明一点,每一种方式都不是十全十美的,关键要看自己的需求,从而分析出哪种实现方式是最合适的。

行内元素

首先我们先把基础代码写出来:

<div class="main">
    <span class="content">我是要居中的行内元素span</span>
</div>
.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;
}

.content {
    background-color: #5b4d4e;
    color: #FFFFFF;
}

class 为 .main 的 div 包裹这一个 class 为 .content 的行内元素 span,我们的目的就是要让 .content 元素 在 .main 元素中居中。

水平居中

text-align

行内元素的水平居中比较简单,我们直接在 .main 中添加 text-align: center; 即可,此时 .main 变为:

.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;

    text-align: center;  /* 水平居中 */
}

实现原理: 设置 text-align 的值为 center ,因为该属性规定元素中的文本的水平对齐方式,那么设置为 center 则文本就水平居中了。

垂直居中

line-height

行内元素的垂直居中我们分为 一行多行或者图片等替换元素 来说明。

如果是 一行,那么我们可以使用 line-height 来实现,此时 .main 元素 css 代码变为:

.main {
    width: 300px;
    height: 300px; /* 可以不设置 */
    background-color: #50ba8b;

    line-height: 300px; /* 垂直居中 */
}

其实设置了 line-height 就可以让文本垂直居中,并不需要同时设置 height,这里也是一直存在的一个误区。

实现原理: 这种方式实现垂直居中运用的是 CSS 中“行距的上下等分机制”,这也说明了为什么该方式只适用于 一行 的文本。

还有一点需要说明是,这种方式实现的垂直居中是“近似”的,并不是完美的垂直居中,因为文字字形的垂直中线位置普遍要比真正的“行框盒子”的垂直中线位置低,而由于我们平时使用的 font-size 比较小,使得这点偏差不容易察觉出来,那么感官上也就看成是垂直居中了。

line-height 及 vertical-align

下面再来说说 多行或者图片等替换元素 的垂直居中效果实现,这里我们需要同时借助 line-heightvertical-align 来实现。

先让文本换行:

<div class="main">
    <span class="content">
        我是要居中的行内元素span <br>
        我是要居中的行内元素span
    </span>
</div>

再看修改之后的 css 代码:

.main {
    width: 300px;
    background-color: #50ba8b;

    line-height: 300px;
}

.content {
    display: inline-block;
    background-color: #5b4d4e;
    color: #FFFFFF;
    line-height: 20px;
    margin: 0 20px;
    vertical-align: middle;
}

实现原理:

  1. 设置 .content 元素的 display 为 inline-block。作用在于既能重置外部的 line-height 为正常大小,又能保持行内元素特性,从而可以设置 vertical-align 属性,以及产生一个非常关键的“行框盒子”。我们需要的其实并不是这个“行框盒子”,而是每个“行框盒子”都会附带的一个产物 —— “幽灵空白节点”,即一个宽度为 0,表现如同普通字符的看不见的“节点”。有了这个“幽灵空白节点”,我们的 line-height: 300px; 就有了作用的对象,从而相当于在 .content 元素前面撑起了一个高度为 300px 的宽度为 0 的行内元素。
  2. 因为行内元素默认都是基线对齐的,所以我们通过对 .content 元素设置 vertical-align: middle; 来调整多行文本的垂直位置,从而实现我们想要的“垂直居中”效果。这种方式也适用于 图片等替换元素 的垂直居中效果。当然这里的“垂直居中”也是近似的,这是由于 vertical-align 导致的,具体为什么可以深入了解 vertical-align: middle;

块级元素

依然先把基础代码写出来:

<div class="main">
    <div class="content">我是要居中的块级元素div</div>
</div>
.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;
}

.content {
    width: 150px;
    height: 150px;
    background-color: #5b4d4e;
}

class 为 .main 的 div 包裹这一个 class 为 .content 的 块级元素 div,我们的目的就是要让 .content 元素 在 .main 元素中居中。

position + margin: auto

实现代码如下:

.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;

    /*关键代码*/
    position: relative;
}

.content {
    width: 150px;
    height: 150px;
    background-color: #5b4d4e;

    /*关键代码*/
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    margin: auto;
}

实现原理:

  1. 设置 .main 元素为相对定位 position: relative;,这样其子元素设置绝对定位时就相对它了。
  2. 然后设置 .content 元素为绝对定位 position: absolute; 并设置它的 topleftbottomright 都为0,这样该元素的元素的尺寸表现为“格式化宽度和格式化高度”,和 <div> 的“正常流宽度”一样,同属于外部尺寸,也就是尺寸自动填充父级元素的可用尺寸,但由于此时我们设置了 .content 元素的宽高,就限制了元素自动填充,这样就多出来150px的空间了。
  3. 最后我们设置 .content 元素为 margin: auto; ,此时根据 auto 的计算规则,将上下左右剩余空间全部等分了,自然就居中了。

position + margin-left/top

实现代码如下:

.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;

    /*关键代码*/
    position: relative;
}

.content {
    width: 150px;
    height: 150px;
    background-color: #5b4d4e;

    /*关键代码*/
    position: absolute;
    top: 50%;
    left: 50%;
    margin-left: -75px;
    margin-top: -75px;
}

实现原理:

  1. 设置 .main 元素为相对定位 position: relative;,这样其子元素设置绝对定位时就相对它了。
  2. 然后设置 .content 元素为绝对定位 position: absolute; 并设置 top: 50%;left: 50%;,这样.content 元素的左上角就位于 .main 元素的中心了。
  3. 最后设置 .content 元素 margin-left: -75px;margin-top: -75px; 将自身左移及上移宽高的一半,这样 .content 元素的中心处于 .main 元素的中心处,自然就实现了居中效果。
  4. 这种方法的缺点就是需要固定 .content 元素的宽高。

position + translate

实现代码如下:

.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;

    /*关键代码*/
    position: relative;
}

.content {
    width: 150px;
    height: 150px;
    background-color: #5b4d4e;

    /*关键代码*/
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

实现原理:

  1. 设置 .main 元素为相对定位 position: relative;,这样其子元素设置绝对定位时就相对它了。
  2. 然后设置 .content 元素为绝对定位 position: absolute; 并设置 top: 50%;left: 50%;,这样.content 元素的左上角就位于 .main 元素的中心了。
  3. 最后设置 .content 元素 transform: translate(-50%, -50%); 将自身左移及上移宽高的一半,这样 .content 元素的中心处于 .main 元素的中心处,自然就实现了居中效果。
  4. 这种方法的好处就是不需要固定 .content 元素的宽高。

Flexbox

实现代码如下:

.main {
    width: 300px;
    height: 300px;
    background-color: #50ba8b;

    /*关键代码*/
    display: flex;
}

.content {
    width: 150px;
    height: 150px;
    background-color: #5b4d4e;

    /*关键代码*/
    margin: auto;
}

实现原理:

  1. 设置 .main 元素 display: flex;
  2. 然后设置 .content 元素为 margin: auto; 即可实现居中。
  3. 这是毋庸置疑的最佳解决方案,我们不需要设置 .content 元素为绝对定位,margin: auto 自然就可以作用于宽高,而且我们也不需要设置 .content 元素的宽高, 因为Flexbox(伸缩盒)是专门针对这类需求所设计的。
  4. 缺点就是目前浏览器支持程度相对其它方式会低些。

Flexbox 的另一个好处在于,它还可以将匿名容器(即没有被标签包裹的文本节点)垂直居中。比如我们不设置 .main 元素为 display: flex;,而是设置 .content 元素为 display: flex;,并借助 Flexbox 规范所引入的 align-items 和 justify-content 属性,我们可以让它内部的文本也实现居中(我们可以对.main 元素使用相同的属性来使 .content 元素元素居中,但比 margin: auto 方法要更加优雅一些,并且同时起到了回退的作用)。

.content {
    width: 150px;
    height: 150px;
    background-color: #5b4d4e;

    /*关键代码*/
    display: flex;
    align-items: center;
    justify-content: center;
    margin: auto;
}

本文分享自微信公众号 - 前端布道(FontendPreach),作者:赖祥燃

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-28

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • CSS——实现元素的垂直居中

    在写CSS的过程中,我常常谷歌一个东西,就是如何实现元素的垂直居中,水平居中难度还不是很大,但是垂直居中我这个烂记性是写一次忘一次,于是本着好记性不如烂笔头的想...

    Originalee
  • 通过CSS,实现元素反转 原

          今天突然看到ES6还有Reflect 概念,我怎么以前没注意过,赶快去CANIUSE上查一下吧,却意外看到CSS Reflections,竟然可以有...

    申君健
  • 元素居中的多种实现方式!

    优点:只需在子元素child上设置css样式,不用关心父元素的 缺点:兼容性较差,如果需要兼容,更改html样式,改为table样式

    十月梦想
  • css布局 - 两栏自适应布局的几种实现方法汇总

    这种两列布局的样式是我们在平时工作中非常常见的设计,同时也是面试中要求实现的高频题。很有必要掌握以备不时之需:

    xing.org1^
  • CSS-垂直|水平居中问题的解决方法总结

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

    "44年前我们就把人类送上了月球了,但现在我们仍然无法在css中实现垂直居中 -James Anderson" 难题 在CSS中对元素进行水平居中是非常简单的...

    okaychen
  • 让div等块级元素水平以及垂直居中的解决办法

      我们在设计页面的时候,经常要把div等块级元素居中显示,而且是相对页面窗口水平和垂直方向居中显示,如让登录窗口居中显示。我们传统解决的办法是用纯CSS来让d...

    阿豪聊干货
  • 献给前端的小伙伴,祝大家面试顺利!

    HTML相关问题 1.XHTML和HTML有什么区别 HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言 最主要的不同: XHTM...

    用户1667431
  • 50道CSS基础面试题

    慕白
  • 50道CSS面试题(附答案)

    标准盒子模型:宽度=内容的宽度(content)+ border + padding + margin 低版本IE盒子模型:宽度=内容宽度(content+bo...

    用户1093975
  • 年薪30万的前端面试题,你能答对几道?|附答案

    HTML面试题 1.XHTML和HTML有什么区别 HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言 最主要的不同: XHTML 元...

    BestSDK
  • 重构不完全教程集之一

    本文作者:IMWeb 结一 原文出处:IMWeb社区 未经同意,禁止转载 “无上甚深微妙法,百千万劫难遭遇,我今见闻得受持,愿解如来真实义。” ——《...

    IMWeb前端团队
  • 重构不完全教程集之一

    “无上甚深微妙法,百千万劫难遭遇,我今见闻得受持,愿解如来真实义。” ——《开经偈》

    IMWeb前端团队
  • Css 垂直居中

    在 CSS 中对元素进行水平居中是非常简单的:如果它是一个行内元素, 就对它的父元素应用 text-align:center; 如果它是一个块级元素,就对它自身...

    grain先森
  • 前端常见技术点 - CSS / DOM / 布局(43问)

    这里总结一下 WEB 前端面试 CSS 部分的常见问题,同时这些问题也是对一些基础的技术概念和思想的理解。对这些基本知识的掌握程度和深度决定了你的技术层级。高级...

    用户5997198
  • 3.CSS优先级-CSS进阶

    见贤思齊
  • 前端面试题2(CSS)

    对BFC规范(块级格式化上下文:block formatting context)的理解?

    keyWords
  • CSS垂直居中的8种方法,附详细的图文教程

    通过vertical-align:middle实现CSS垂直居中是最常使用的方法,但是有一点需要格外注意,vertical生效的前提是元素的display:in...

    李洋个人博客
  • 解决CSS垂直居中的几种方法(基于绝对定位,基于视口单位,Flexbox方法)

          在CSS中对元素进行水平居中是非常简单的:如果它是一个行内元素,就对它的父元素应用 text-align: center ;如果它是一个块级元素,就...

    李文杨

扫码关注云+社区

领取腾讯云代金券