CSS十问之元素居中

简介: 水平居中垂直居中水平&垂直居中


大多数人都想要改变世界,却罕有人想改变自己

前言

大家好,我是柒八九。从今天起,我们又重新开辟了一个新的领域:CSS串讲。(毕竟在Web 领域,CSS也是有举足轻重的作用)在该系列文章中,我们会一起学习 元素居中层叠上下文还有一些在面试中比较常见的问题及一些在工作中遇到比较好玩的点。

而今天,我们就从 元素居中:这个让无论是前端"萌新"还是"老油条" 抓耳挠腮的问题。不是因为它难,是因为它太杂了。(这也很契合CSS的学习特定:等)

我记得在看张鑫旭在讲解vertical-align和line-height关系文章 提出来一个观点:

为了快速记住新的东西,而采用的常用方式:

- 情感化认知

- 具象化思维

同样,无论是针对前端Js/Css/Html/Vue/React/Webpack/Vite还是一些新的语言Rust想必都有一些你不熟悉或者模棱两可的知识概念和体系。所以,我们可以尝试用上述的方式,来对新的知识点,进行归纳和梳理。其实,这也算是又重新记忆了一次。只不过,这种方式,可能只属于你一个人能懂的知识关联体系。(那又何妨,我记住了,我骄傲)。

佛陀曾说:我不入地狱,谁入地狱 。这些梳理的事情,就交给我哇。你只负责抽空回来看看(放心,我尽量讲的通俗易懂点)。这也算是,一个工作笔记,平时遇到类似的样式处理,可以快速的通过文章进行检索。于公于私,这个活,我接了。

这里还做一个简短的文章说明:该篇文章,接着居中的话题,一方面讲述比较常规的居中处理方式,然后做一个归纳总结,一方面,把一些css中比较晦涩难懂的知识点,做一个简单介绍。而不是把市面上针对样式居中的所有奇技淫巧都囊括到一起。

话不多说,我们发车了!

简明扼要

  1. 块级元素和displayblock的元素不是一个概念
  2. 对于非替换元素,当left/righttop/bottom,对立方位的属性值同时存在的时候,元素的宽度表现为格式化宽度,其宽度大小相对于最近的具有定位特性(position属性值不是static)的祖先元素计算
  3. margin:auto就是为了填充闲置尺寸而设计的
    1. 如果一侧定值,一侧auto,则auto为剩余空间大小
    2. 如果两侧都是auto,则平分剩余空间
  4. {行高|Line-height}: 指上下文本行基线间的垂直距离
  5. 对于非替换元素的纯内联元素,其可视高度完全line-height决定
  6. 行高实现垂直居中原因在于CSS中行距的上下等分机制

针对居中我们有一个打油诗

-样式居中分两类,水平/垂直惹人怜;

- 每个模式差不离,既定套路得人心;

- 首把元素类型定,行内/块级是旋律;

- 行内水平center一招鲜,垂直padding/line-height/table齐上阵

- 块级首看宽/高是否定,水平常规marigin:auto

- 无论宽/高是否定,子绝父相上绝活

- 无论水平或垂直,遇事不决flex/grid

文章概要

  1. 水平居中
  2. 垂直居中
  3. 水平&垂直居中

知识点简讲

元素分类

CSS世界中,基本上分为两类元素

  • 块级元素
  • 行内元素

常见的块级元素有div/li/table。它们最主要的特点就是:一个水平流上只能单独显示一个块元素

这里有一个点,需要大家厘清:

块级元素和displayblock的元素不是一个概念

例如:


  • 元素默认的display值是list-item
  • 元素默认的display值是table

    其实,如果再往深挖一下的话,有一个结论:

    每个元素都有两个盒子

    外在盒子: 负责元素是可以一行显示,还是只能换行显示

    内在盒子:负责宽高、内容呈现

    按照display的属性值不同,

    • block: 外在盒子: 块级盒子;内在盒子:块级容器盒子
    • inline-block:外在盒子:内联盒子;内在盒子:块级容器盒子
    • inline:外在盒子:内联盒子;内在盒子:内联盒子

    既然有了前面的针对元素内/外盒子的描述,我们很自然的就联想到。

    内联元素:元素的外在盒子具有内联性,具体表现就是 该元素可以和文字在一行显示。

    更进一步的讲,我们可以将 displayinline或者inline-*的元素,简单的划分为内联元素。


    width:auto

    width的默认值是auto

    width:auto不同的宽度表现

    1. {充分利用可用空间|Fill-Available}

      /

      宽度默认是100%父容器

    2. {收缩与包裹|Shrink-to-Fit}:典型代表有浮动绝对定位inline-blocktable元素
    3. 收缩到最小
    4. 超出容器限制: 具体表现为 内容很长的连续英文和数字或者内联元素被设置white-space:nowrap;

    元素尺寸

    尺寸分为两类

    1. 内部尺寸:尺寸由内部元素决定
    2. 外部尺寸:尺寸由外部元素决定

    外部尺寸的范畴内,针对宽度的又分为两类:

    1. 正常流宽度
    2. 格式化宽度

    而外部尺寸的块级元素一旦设置了宽度,流动性就丢失了。

    流动性:并不是看上去宽度100%显示那么简单,而是一种margin/border/paddingcontent内容区自动分配水平空间的机制

    格式化宽度:默认情况下,绝对定位元素的宽度表现是包裹性宽度由内部尺寸决定

    格式化宽度的具体表现为:

    对于非替换元素,当left/righttop/bottom,对立方位的属性值同时存在的时候,元素的宽度表现为格式化宽度,其宽度大小相对于最近的具有定位特性(position属性值不是static)的祖先元素计算

    有几个重要的点可以简单记住

    1. 非替换元素
    2. position:absolute/fixed
    3. 对立方位同时有值
    4. 相对最近的有定位属性的祖先元素

    从侧面说明了,格式化宽度具有流动性。


    margin:auto

    margin:auto就是为了填充闲置尺寸而设计的

    margin:auto用来计算元素对应方向应该获得的剩余间距大小。对应的规则如下:

    1. 如果一侧定值,一侧auto,则auto为剩余空间大小
    2. 如果两侧都是auto,则平分剩余空间

    而如何让一个块级元素右对齐margin-left:auto才是最佳实践。margin属性的auto计算就是为块级元素左中右对齐而设计的。


    {行高|Line-height}、行距与半行距

    • {上行线高度| ascender height}
    • {大写字母高度| cap height}
    • {基线| baseline}
    • {中线/等分线| median}
    • {下行线高度| descender height}

    • {行高|Line-height}: 指上下文本行基线间的垂直距离,即图中两条红线间垂直距离。
    • 行距: 指一行底线到下一行顶线的垂直距离,即第一行粉线和第二行绿线间的垂直距离。
    • 半行距:行距的一半,即区域3垂直距离/2,
    • 区域1,2,3,4的距离之和为行高
    • 区域1,2,4距离之和为font-size,所以半行距也可以这么算:(行高-字体size)/2

    {行高|Line-height}:内联元素的基石

    line-height:是内联元素的高度之本

    对于非替换元素的纯内联元素,其可视高度完全line-height决定

    内联元素的高度由固定高度不固定高度组成。不固定高度就是行距。换句话说:

    line-height就是通过改变行距来改变内联元素高度的

    行距 = 行高 - em-boxem-box高度正好就是1em,而em是一个相对font-size大小的CSS单位。即:1em等于当前一个font-size大小。

    进而,我们可得出另外一个结论:

    行距 = line-height - font-size

    line-height比较重要的作用是: 让内联元素垂直居中,而

    行高实现垂直居中原因在于CSS中行距的上下等分机制

    但是,这种是近似居中:文字字形的垂直中线位置普遍要比真正的行框盒子的垂直中线位置低


    1. 水平居中

    行内元素-水平居中

    针对某个块级元素,然后想让其内联子元素,水平居中。

    // 行内元素-水平居中
    .center-inline {
      text-align: center;
    }
    复制代码

    示例比较简单,就不贴具体的html代码了。

    固定宽度的块级元素-水平居中

    // 固定宽度的块级元素-水平居中
    .center-block-fixed-width {
      margin: 0 auto;
    }
    复制代码

    请注意,在该情况下,是两种情况都需要满足,才可以利用这种方式对元素进行居中处理。

    1. 块级元素
    2. 固定宽度

    这两个是&的关系,两者缺一不可。并且,根据前置知识中关于margin:auto的介绍。很自然就会想明白为何通过maring:0 auto就可以将定宽的块级元素水平居中了。

    我们继续来解释下,首先,块级元素定宽,也就是说该元素流动性消失了,不会100%于父级元素的宽度了。换言之,就是该元素在水平方向无法将父元素填充满。既然,存在了闲置空间,那么,margin:auto就是干这个事的,所以他们两个一拍即合。

    我们将这个例子世俗化一下:将块级元素,想象成某个当红小生。在神秘力量的驱使下,当红小生原来左右逢源(占满一行)的粉丝市场被束缚了(定宽了),没法拥有原来的荣光了,又想占据C位,自身实力不够,那就需要贵人扶持。在margin:auto这个贵人的大力支持下,这位小生又站起来了。(居中了)

    多个块级元素-水平居中如果有一个需求,需要将多个块级元素水平居中。

    // xx 会被后续的特定的类名替换
    <main class="xx-center">
      <div>
        块1
      </div>
      <div>
        块2
      </div>
      <div>
         块3
      </div>
    </main>
    复制代码

    这里有两种比较常规的处理方式。

    1. 将块级元素inline-block
    2. 利用flexbox

    inline-block

    // 父元素 设置水平居中
    .inline-block-center {
      text-align: center;
    }
    // 块级元素 `inline-block`化
    .inline-block-center div {
      display: inline-block;
      text-align: left;
    }
    复制代码

    具体原理,其实和针对内行元素水平居中是一个道理。这里不做过多解释。

    利用flexbox

    .flex-center {
      display: flex;
      justify-content: center;
    }
    复制代码

    父级元素设置display:flex,成为 {Flex 容器| Flex Container },简称"容器"。它的所有子元素自动成为容器成员,称为 {Flex 项目| Flex Item },简称"项目"。

    同时,在容器上设置justify-content,该属性定义了项目在主轴上的对齐方式。

    .box {
      justify-content: flex-start | flex-end | center | space-between | space-around;
    }
    复制代码

    它可能取5个值,具体对齐方式与轴的方向有关

    • flex-start(默认值):左对齐
    • flex-end:右对齐
    • center: 居中
    • space-between:两端对齐,项目之间的间隔都相等。
    • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

    针对Flex的具体细节,可以参考阮一峰老师写的Flex 布局教程:语法篇,这里也不做延伸。


    2. 垂直居中

    行内元素-垂直居中

    针对行内元素的垂直居中,有分两种情况

    1. 单行垂直居中
    2. 多行垂直居中

    单行垂直居中

    例如,现在希望某个行内元素的文案在垂直方向居中显示。通过对该元素设置上下方向设置pading。以到达将文本信息,放置到中间位置的效果。

    .center-text-vertical {
      padding-top: 30px;
      padding-bottom: 30px;
    }
    复制代码

    如果,在有些情况下,padding属性无法生效(反正就是不让用),并且当前文本信息不会换行,即white-space:nowrap。此时,就需要另外一种邪门外道: 设置line-height

    .center-text-vertical-trick {
      line-height: 100px;
      white-space: nowrap;
    }
    复制代码

    多行垂直居中

    针对多行元素在垂直方向的居中,通过在利用table元素的td默认属性:即在垂直方向上vertical-align: middle;

    <table>
      <tr>
        <td>
         我是一个多行文本信息 bala bala 
        </td>
      </tr>
    </table>
    复制代码

    这种其实是直接利用了table元素的默认属性,实现想要的效果。

    有时候,我们不想用table进行页面布局。所以,我们就利用display:table手动将某些元素指定为拥有table布局属性的元素。

    <div class="center-table">
      <p>我是一个多行文本信息 bala bala </p>
    </div>
    复制代码

    由于行文所限,只写出特定的布局样式。

    .center-table {
      display: table;
    }
    .center-table p {
      display: table-cell;
      // 手动指定 垂直方向居中显示
      vertical-align: middle;
    }
    复制代码

    如果还嫌弃麻烦的话,我们还有另外一种方式。只需要在父级元素中设置特定的属性,对应的子元素就会在垂直方向上居中显示。

    那就是flex布局。

    <div class="flex-center">
      <p>我是一个多行文本信息 bala bala</p>
    </div>
    复制代码

    在父级元素,一劳永逸的设置子元素居中样式

    .flex-center {
      display: flex;
      flex-direction: column;
      justify-content: center;
      height:200px;  //这里不能缺少
    } 
    复制代码

    Note: 如果想让居中效果有效,有一个前提条件就是,父级元素必须有一个定高(px,%)。

    如果,高度无法定死,那就需要另辟蹊径了。利用一个伪类::before采用幽灵节点来实现。

    <div class="ghost-center">
      <p>我是一个多行文本信息 bala bala</p>
    </div>
    复制代码

    对应的样式代码如下:

    .ghost-center {
      position: relative;
    }
    .ghost-center::before {
      content: " ";
      display: inline-block;
      // 画龙点睛之笔
      height: 100%;
      width: 1%;
      vertical-align: middle;
    }
    .ghost-center p {
      display: inline-block;
      vertical-align: middle;
    }
    复制代码

    块级元素-垂直居中

    元素定高

    .parent {
      position: relative;
    }
    .child {
      position: absolute;
      top: 50%;
      height: 100px;
      margin-top: -70px; 
      padding:20px;
    }
    复制代码

    这里有几点,需要注意

    • 父元素 position:relative
    • 子元素: position:absolute
    • margin-x: 此时x和top/bottom一致
      在没有设置box-sizing: border-box情况下,需要 height/2 + padding-x+ border-x

    元素高度不确定

    在元素高度确定的情况下,我们可以通过height/2 + padding-x+ border-x等公式计算出,需要在垂直方向移动的距离。但是,针对元素高度不定的情况,我们就需要想其他的办法了。

    .parent {
      position: relative;
    }
    .child {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
    }
    复制代码

    使用flex

    高端的代码,都是朴实无华且简单。

    .parent {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    复制代码

    3. 元素水平垂直居中

    针对处理这类问题,我们可以通过将 水平居中垂直居中合并起来。可以有(M*N)的解法。但是,在平时工作中,大致可分为四类。

    宽&高固定

    使用负marigin有很好的兼容性

    absolute + 负 margin

    .parent {
      position: relative;
    }
    .child {
      width: 300px;
      height: 100px;
      padding: 20px;
      position: absolute;
      top: 50%;
      left: 50%;
      margin: -70px 0 0 -170px;
    }
    复制代码

    这里的marigin的计算还是和box-sizing的值强相关。具体细节,可以参考,垂直居中关于这里的解释。

    当然,还有一些类似的处理方式也是可以的。例如

    absolute + margin auto

    利用了,针对margin属性, 如果两侧都是auto,则平分剩余空间

    absolute + calc

    宽&高不固定

    .parent {
      position: relative;
    }
    .child {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    复制代码

    flex布局

    .parent {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    复制代码

    grid 布局

    .parent {
      display:grid;
    }
    .parent .child{
      margin:auto;
    }
    复制代码

    后记

    分享是一种态度,这篇文章,参考很多文章,算是一个自我学习过程中的一种记录和总结。主要是把自己认为重要的点,都罗列出来。同时,也是为大家节省一下排雷和踩坑的时间。当然,可能由于自己认知能力所限,有些点,没能表达很好。

    参考资料:

    1. centering-css
    2. flex
    3. 张鑫旭 《CSS进阶》
相关文章
|
6月前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
伪类:伪类这个叫法源自于它们跟类相似,但实际上并没有类会附加到标记中的标签上。 伪类分为两种(以及新增的伪类选择器): UI伪类:会在HTML元素处于某种状态时(例如:鼠标指针位于连接上),为该元素应用CSS样式。 :hover 结构化伪类:会在标记中存在某种结构上的关系时 例如: 某元素是一组元素中的第一个或最后一个,为该元素应用CSS样式。 :not和:target(CSS3新增的两个特殊的伪类选择器)
710 2
|
6月前
|
前端开发 算法 Java
(CSS)使用Flex布局,帮助你快速了解各种基本的Flex布局属性以及帮你让元素快速达到布局中的指定位置!
(CSS)使用Flex布局,帮助你快速了解各种基本的Flex布局属性以及帮你让元素快速达到布局中的指定位置!
213 1
|
6月前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
Flex 布局 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。 2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。 一、Flex 布局是什么? Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
438 0
|
6月前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
盒模型 盒模型: 所谓盒模型,就是浏览器为页面中的每个HTML元素生成的矩形盒子。 这些盒子们都要按照可见板式模型在页面上排布。 可见的板式模型主要由三个属性控制:position 属性、display 属性和 float属性。 position属性控制页面上元素间的位置关系。 display属性控制元素是堆叠、并排或者不在页面上显示。 float属性提供控制的方法,以便于把元素组成成多栏布局。 盒模型讲解: 在默认的情况下,每个盒子的边框是不可见的,背景也是透明的。 所以我们 不能直接的看到页面中的盒
865 1
|
6月前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
继承 我们的CSS中很多的属性也是可以继承的,其中相当一部分是跟文字的相关的,比如说颜色、字体、字号。 当然还有一部分是不能继承的。 例如边框、内外边距。 层叠 层叠是CSS的核心机制。 层叠的工作机制: 当元素的同一个样式属性有多种样式值的时候,CSS就是靠层叠机制来决定最终应用哪种样式。 层叠规则: 层叠规则一:找到应用给每个元素和属性的声明。 说明:浏览器在加载每个页面时,都会据此查找到每条CSS规则, 并标识出所有受到影响的HTML元素。
230 0
|
前端开发 JavaScript
如何使用CSS过渡实现页面元素的淡入淡出效果?
如何使用CSS过渡实现页面元素的淡入淡出效果?
619 79
|
前端开发 JavaScript
如何利用 CSS3 动画实现元素的淡入淡出效果?
在上述代码中,定义了一个名为 `fade-in` 的CSS类,其初始透明度为0,并设置了淡入的过渡效果。当通过JavaScript为元素添加 `active` 类时,元素的透明度变为1,实现淡入效果;当再次点击按钮移除 `active` 类时,元素又会逐渐淡出。通过这种方式,可以根据用户的操作灵活地控制元素的淡入淡出效果。
1850 60
|
数据采集 前端开发 JavaScript
捕捉页面的关键元素:用CSS选择器与Puppeteer自动抓取
本文介绍了如何使用 Puppeteer 结合 CSS 选择器抓取动态网页中的关键元素,以亚航网站的特价机票信息为例,通过设置代理 IP、User-Agent 和 Cookie 等技术手段,有效提升爬虫策略,实现高效、稳定的爬取。
436 5
捕捉页面的关键元素:用CSS选择器与Puppeteer自动抓取
|
前端开发 JavaScript UED
CSS滚动效果和视差滚动的原理、应用及其对用户体验的影响。从平滑滚动到元素跟随,再到滚动触发动画
本文探讨了CSS滚动效果和视差滚动的原理、应用及其对用户体验的影响。从平滑滚动到元素跟随,再到滚动触发动画,这些效果增强了页面的吸引力和互动性。视差滚动通过不同层次元素的差异化移动,增加了页面的深度感和沉浸感。文章还讨论了实现方法、性能优化及案例分析,旨在为设计师和开发者提供实用指导。
416 7
|
前端开发 容器
最新CSS3定位元素
【8月更文挑战第28天】
191 5