别再用 float 布局了,flex 才是未来!

大家好,我是树哥!

前面一篇文章整体介绍了 CSS 的布局知识,其中说到 float 布局是 CSS 不断完善的副产物。而在 2023 年的今天,flex 这种布局方式才是未来!那么今天我们就来学习下 flex 弹性布局。

什么是 Flex 布局?

在经过了长达 10 年的发展之后,CSS3 才终于迎来了一个简单好用的布局属性 ------ flex。Flex 布局又称弹性布局,它使用 flexbox 属性使得容器有了弹性,可以自动适配各种设备的不同宽度,而不必依赖于传统的块状布局和浮动定位。

举个很简单地例子,如果我们想要实现一个很简单左侧定宽,右侧自适应的导航布局,如下图所示。

在没有 flex 之前,我们的代码是这么写的。

html 复制代码
<div>
<h1>4.1 两栏布局 - 左侧定宽、右侧自适应 - float</h1>
<div class="container">
  <div class="left41"></div>
  <div class="right41"></div>
</div>
</div>
css 复制代码
/** 4.1 两栏布局 - 左侧定宽、右侧自适应 - float **/
.left41 {
  float: left;
  width: 300px;
  height: 500px;
  background-color: pink;
}
.right41 {
  width: 100%;
  height: 500px;
  background-color: aquamarine;
}

这种方式不好的地方在于,我们还需要去理解 float 这个概念。一旦需要理解 float 这个概念,我们就会拖出一大堆概念,例如文档流、盒子模型、display 等属性(虽然这些东西确实应该学)。但对于 flex 来说,它就很简单,只需要设置一个伸缩系数即可,如下代码所示。

html 复制代码
<div>
<h1>4.2 两栏布局 - 左侧定宽、右侧自适应 - flex</h1>
<div class="container42">
  <div class="left42"></div>
  <div class="right42"></div>
</div>
</div>
css 复制代码
.container42 {
  display: flex;
}
.left42 {
  width: 300px;
  height: 500px;
  background-color: pink;
}
.right42 {
  flex: 1;
  width: 100%;
  height: 500px;
  background-color: aquamarine;
}

上面的代码里,我们只需要将父级容器设置为 flex 展示形式(display: flex),随后在需要自动伸缩的容器里设置属性即可。上面代码中的 flex: 1 表示其占据所有其他当行所剩的空间。通过这样的方式,我们非常方便地实现了弹性布局。

当然,上面只是一个最简单的例子,甚至还不是很能体现出 flex 的价值。flex 除了在响应式布局方面非常方便之外,它在对齐等方面更加方便,能够极大地降低学习成本、提高工作效率。

Flex 核心概念

对于 Flex 布局来说,其有几个核心概念,分别是:主轴与交叉轴、起始线和终止线、Flex 容器与 Flex 容器项。

主轴和交叉轴

在 Flex 布局中有一个名为 flex-direction 的属性,可以取 4 个值,分别是:

  • row
  • row-reverse
  • column
  • column-reverse

如果你选择了 row 或者 row-reverse,那么主轴(Main Axis)就是横向的 X 轴,交叉轴(Cross Axis)就是竖向的 Y 轴,如下图所示。

如果你选择了 column 或者 column-reverse,那么主轴(Main Axis)就变成是竖向的 Y 轴,交叉轴(Cross Axis)就是横向的 X 轴,如下图所示。

起始线和终止线

过去,CSS 的书写模式主要被认为是水平的,从左到右的。但现代的布局方式涵盖了书写模式的范围,所以我们不再假设一行文字是从文档的左上角开始向右书写的。

对于不同的语言来说,其书写方向不同,例如英文是从左到右,但阿拉伯文则是从右到左。那么对于这两种语言来说,其xx会有所不同 TODO。举个简单的例子,如果 flex-direction 是 row ,并且我是在书写英文。由于英文是从左到右书写的,那么主轴的起始线是左边,终止线是右边,如下图所示。

但如果我在书写阿拉伯文,由于阿拉伯文是从右到左的,那么主轴的起始线是右边,终止线是左边,如下图所示。

在 Flex 布局中,起始线和终止线决定了 Flex 容器中的 Flex 元素从哪个方向开始排列。 举个简单例子,如果我们通过 direction: ltr 设置了文字书写方向是从左到右,那么起始线就是左边,终止线就是右边。此时,如果我们设置的 flex-direction 值是 row,那么 Flex 元素将会从左到右开始排列。但如果我们设置的 flex-direction 值是 row-reverse,那么 Flex 元素将会从右到左开始排列。

在上面的例子中,交叉轴的起始线是 flex 容器的顶部,终止线是底部,因为两种语言都是水平书写模式。但如果有一种语言,它的书写形式是从底部到顶部,那么当设置 flex-direction 为 column 或 column-reverse 时,也会有类似的变化。

Flex 容器与 Flex 元素

我们把一个容器的 display 属性值改为 flex 或者 inline-flex 之后,该容器就变成了 Flex 容器,而容器中的直系子元素就会变为 flex 元素。如下代码所示,parent 元素就是 Flex 容器,son 元素就是 Flex 元素。

html 复制代码
<style>
#parent {
    display: flex;
}
</style>
<div id="parent">
    <div id="son"></div>
</div>

Flex 核心属性

对于 Flex 来说,它有非常多的用法,但核心属性却相对较少。这里我只简单介绍几个核心属性,如果你想了解更多 Flex 的属性,可以去 Mozilla 官网查询,这里给个传送门:flex 布局的基本概念 - CSS:层叠样式表 | MDN

对于 Flex 布局来说,其核心属性有如下几个:

  1. flex-direction 主轴方向
  2. flex 伸缩系数及初始值
  3. justify-content 主轴方向对齐
  4. align-items 交叉轴方向对齐

flex-direction 主轴方向

如上文所介绍过的,flex-direction 定义了主轴的方向,可以取 4 个值,分别是:

  • row 默认值
  • row-reverse
  • column
  • column-reverse

一旦主轴确定了,交叉轴也确定了。主轴和交叉轴与后续的对齐属性有关,因此弄懂它们非常重要!举个很简单的例子,如下的代码将展示下图的展示效果。

.box {
  display: flex;
  flex-direction: row-reverse;
}

<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

如果你将 flex-direction 改成 column-reverse,那么将会变成如下的效果,如下图所示。

flex 伸缩系数及初始值

前面说到 Flex 布局可以很方便地进行响应式布局,其实就是通过 flex 属性来实现的。flex 属性其实是 flex-grow、flex-shrink、flex-basis 这三个参数的缩写形式,如下代码所示。

css 复制代码
flex-grow: 1;
flex-shrink: 1;
flex-basis: 200px;
/* 上面的设置等价于下面 flex 属性的设置 */
flex: 1 1 200px;

在考虑这几个属性的作用之前,需要先了解一下 可用空间 available space 这个概念。这几个 flex 属性的作用其实就是改变了 flex 容器中的可用空间的行为。

假设在 1 个 500px 的容器中,我们有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,剩下 200px 的可用空间。在默认情况下,flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。

如果期望这些元素能自动地扩展去填充满剩下的空间,那么我们需要去控制可用空间在这几个元素间如何分配,这就是元素上的那些 flex 属性要做的事。

flex-basis

flex-basis 属性用于设置 Flex 元素的大小,其默认值是 auto。此时浏览器会检查元素是否有确定的尺寸,如果有确定的尺寸则用该尺寸作为 Flex 元素的尺寸,否则就采用元素内容的尺寸。

flex-grow

flex-grow 若被赋值为一个正整数,flex 元素会以 flex-basis 为基础,沿主轴方向增长尺寸。这会使该元素延展,并占据此方向轴上的可用空间(available space)。如果有其他元素也被允许延展,那么他们会各自占据可用空间的一部分。

举个例子,上面的例子中有 a、b、c 个 Flex 元素。如果我们给上例中的所有元素设定 flex-grow 值为 1,容器中的可用空间会被这些元素平分。它们会延展以填满容器主轴方向上的空间。

但很多时候,我们可能都需要按照比例来划分剩余的空间。此时如果第一个元素 flex-grow 值为 2,其他元素值为 1,则第一个元素将占有 2/4(上例中,即为 200px 中的 100px), 另外两个元素各占有 1/4(各 50px)。

flex-shrink

flex-grow 属性是处理 flex 元素在主轴上增加空间的问题,相反 flex-shrink 属性是处理 flex 元素收缩的问题。如果我们的容器中没有足够排列 flex 元素的空间,那么可以把 flex 元素 flex-shrink 属性设置为正整数,以此来缩小它所占空间到 flex-basis 以下。

与flex-grow属性一样,可以赋予不同的值来控制 flex 元素收缩的程度 ------ 给flex-shrink属性赋予更大的数值可以比赋予小数值的同级元素收缩程度更大。

justify-content 主轴方向对齐

justify-content 属性用来使元素在主轴方向上对齐,它的初始值是 flex-start,即元素从容器的起始线排列。justify-content 属性有如下 5 个不同的值:

  • flex-start:从起始线开始排列,默认值。
  • flex-end::从终止线开始排列。
  • center:在中间排列。
  • space-around:每个元素左右空间相等。
  • space-between:把元素排列好之后,剩余的空间平均分配到元素之间。

各个不同的对齐方式的效果如下图所示。

flex-start:

flex-end:

center:

space-around:

space-between:

align-items 交叉轴方向对齐

align-items 属性可以使元素在交叉轴方向对齐,它的初始值是 stretch,即拉伸到最高元素的高度。align-items 属性有如下 5 个不同的值:

  • stretch:拉伸到最高元素的高度,默认值。
  • flex-start:按 flex 容器起始位置对齐。
  • flex-end:按 flex 容器结束为止对齐。
  • center:居中对齐。
  • baseline:始终按文字基线对齐。

各个不同的对齐方式的效果如下图所示。

stretch:

flex-start:

flex-end:

center:

要注意的事,无论 align-items 还是 justify-content,它们都是以主轴或者交叉轴为参考的,而不是横向和竖向为参考的,明白这点很重要。

Flex 默认属性

由于所有 CSS 属性都会有一个初始值,所以当没有设置任何默认值时,flex 容器中的所有 flex 元素都会有下列行为:

  • 元素排列为一行 (flex-direction 属性的初始值是 row)。
  • 元素从主轴的起始线开始。
  • 元素不会在主维度方向拉伸,但是可以缩小。
  • 元素被拉伸来填充交叉轴大小。
  • flex-basis 属性为 auto。
  • flex-wrap 属性为 nowrap。

弄清楚 Flex 元素的默认值有利于我们更好地进行布局排版。

实战项目拆解

看了那么多的 Flex 布局知识点,总感觉干巴巴的,是时候来看看别人在项目中是怎么用的了。

上面是我在 CodePen 找到的一个案例,这样的一个布局就是用 Flex 布局来实现的。通过简单的分析,其实我们可以拆解出其 Flex 布局方法,大致如下图所示。

首先整体分为两大部分,即导航栏和内容区域,这部分的主轴纵向排列的(flex-direction: column),如上图红框部分。随后在内容区域,又将其分成了左边的导航栏和右边的内容区域,此时这块内容是横向排列的(flex-direction: row),如下上图蓝框部分。

剩下的内容布局也大致类似,其实就是无限套娃下去。由于偏于原因,这里就不继续深入拆解了,大致的布局思路已经说得很清楚了。

有了 Flex 布局之后,貌似布局也变得非常简单了。但纸上得来终觉浅,还是得自己实际动手练练才知道容易不容易,不然就变成纸上谈兵了!

总结

看到这里,关于 Flex 布局的核心点就介绍得差不多了。掌握好这几个核心的知识点,开始去实践练习基本上没有什么太大的问题了。剩下的一些比较小众的属性,等用到的时候再去查查看就足够了。

接下来更多的时间,就是找多几个实战案例实践,唯有实践才能巩固所学知识点。后面有机会,我将分享我在 Flex 布局方面的项目实践。

如果这篇文章对你有帮助,记得一键三连支持我!

参考资料

相关推荐
请叫我飞哥@6 小时前
HTML5 CSS 与样式详解
前端·css·html5
小马哥编程8 小时前
原型链(Prototype Chain)入门
css·vue.js·chrome·node.js·原型模式·chrome devtools
娃哈哈哈哈呀12 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
sunshine64114 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
lv程序媛16 小时前
css让按钮放在最右侧
前端·css
温轻舟16 小时前
前端开发 之 12个鼠标交互特效上【附完整源码】
开发语言·前端·javascript·css·html·交互·温轻舟
linda_060719 小时前
定位方式:css
前端·css
安冬的码畜日常20 小时前
【CSS in Depth 2 精译_086】14.3:CSS 剪切路径(clip-path)的用法
前端·css·css3·html5·clip-path·css剪辑·css剪切路径