前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CSS十问之元素居中

CSS十问之元素居中

作者头像
前端柒八九
发布2022-08-25 14:51:31
1.7K0
发布2022-08-25 14:51:31
举报
文章被收录于专栏:柒八九技术收纳盒

前言

大家好,我是柒八九。从今天起,我们又重新开辟了一个新的领域: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的元素不是一个概念 ❞

例如:

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

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

❝每个元素都有「两个盒子」 「外在盒子」:负责元素是可以一行显示,还是只能换行显示 「内在盒子」:负责宽高、内容呈现 ❞

按照display的属性值不同,

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

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

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

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


width:auto

width的默认值是auto

width:auto不同的宽度表现

  1. 充分利用可用空间Fill-Available:<div>/<p>宽度默认是100%「父容器」
  2. 收缩与包裹Shrink-to-Fit:典型代表有「浮动」「绝对定位」「inline-block」「table元素」
  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. 水平居中

行内元素-水平居中

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

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

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

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

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

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

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

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

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

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

多个块级元素-水平居中

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

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

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

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

inline-block

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

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

利用flexbox

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

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

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

代码语言:javascript
复制
.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。以到达将文本信息,放置到中间位置的效果。

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

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

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

多行垂直居中

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

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

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

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

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

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

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

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

那就是flex布局。

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

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

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

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

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

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

对应的样式代码如下:

代码语言:javascript
复制
.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;
}

块级元素-垂直居中

元素定高

代码语言:javascript
复制
.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等公式计算出,需要在垂直方向移动的距离。但是,针对元素高度不定的情况,我们就需要想其他的办法了。

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

使用flex

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

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

3. 元素水平垂直居中

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

宽&高固定

使用负marigin有很好的「兼容性」

absolute + 负 margin

代码语言:javascript
复制
.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

宽&高不固定

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

flex布局

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

grid 布局

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

后记

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

参考资料:

  1. centering-css
  2. flex
  3. 张鑫旭 《CSS进阶》
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端柒八九 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 简明扼要
  • 文章概要
  • 知识点简讲
    • 元素分类
      • width:auto
        • 元素尺寸
          • margin:auto
            • 行高Line-height、行距与半行距
              • 行高Line-height:内联元素的基石
              • 1. 水平居中
                • 行内元素-水平居中
                  • 固定宽度的块级元素-水平居中
                    • 多个块级元素-水平居中
                      • inline-block
                      • 利用flexbox
                  • 2. 垂直居中
                    • 行内元素-垂直居中
                      • 单行垂直居中
                      • 多行垂直居中
                    • 块级元素-垂直居中
                      • 元素定高
                      • 元素高度不确定
                      • 使用flex
                  • 3. 元素水平垂直居中
                    • 宽&高固定
                      • absolute + 负 margin
                      • absolute + margin auto
                      • absolute + calc
                    • 宽&高不固定
                      • flex布局
                        • grid 布局
                        • 后记
                        相关产品与服务
                        容器服务
                        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档