别再用 float 布局了,flex 才是未来!
大家好,我是树哥!
前面一篇文章整体介绍了 CSS 的布局知识,其中说到 float 布局是 CSS 不断完善的副产物。而在 2023 年的今天,flex 这种布局方式才是未来!那么今天我们就来学习下 flex 弹性布局。
什么是 Flex 布局?
在经过了长达 10 年的发展之后,CSS3 才终于迎来了一个简单好用的布局属性 —— flex。Flex 布局又称弹性布局,它使用 flexbox 属性使得容器有了弹性,可以自动适配各种设备的不同宽度,而不必依赖于传统的块状布局和浮动定位。
举个很简单地例子,如果我们想要实现一个很简单左侧定宽,右侧自适应的导航布局,如下图所示。

在没有 flex 之前,我们的代码是这么写的。
<div>
<h1>4.1 两栏布局 - 左侧定宽、右侧自适应 - float</h1>
<div class="container">
<div class="left41"></div>
<div class="right41"></div>
</div>
</div>
/** 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 来说,它就很简单,只需要设置一个伸缩系数即可,如下代码所示。
<div>
<h1>4.2 两栏布局 - 左侧定宽、右侧自适应 - flex</h1>
<div class="container42">
<div class="left42"></div>
<div class="right42"></div>
</div>
</div>
.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 元素。
<style>
#parent {
display: flex;
}
</style>
<div id="parent">
<div id="son"></div>
</div>
Flex 核心属性
对于 Flex 来说,它有非常多的用法,但核心属性却相对较少。这里我只简单介绍几个核心属性,如果你想了解更多 Flex 的属性,可以去 Mozilla 官网查询,这里给个传送门:flex 布局的基本概念 - CSS:层叠样式表 | MDN。
对于 Flex 布局来说,其核心属性有如下几个:
- flex-direction 主轴方向
- flex 伸缩系数及初始值
- justify-content 主轴方向对齐
- 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 这三个参数的缩写形式,如下代码所示。
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 布局方面的项目实践。
如果这篇文章对你有帮助,记得一键三连支持我!
参考资料
别再用 float 布局了,flex 才是未来!的更多相关文章
- CSS布局:Float布局过程与老生常谈的三栏布局
原文见博客主站,欢迎大家去评论. 使用CSS布局网页,那是前端的基本功了,什么两栏布局,三栏布局,那也是前端面试的基本题了.一般来说,可以使用CSSposition属性进行布局,或者使用CSSfloa ...
- 转:CSS布局:Float布局过程与老生常谈的三栏布局
使用CSS布局网页,那是前端的基本功了,什么两栏布局,三栏布局,那也是前端面试的基本题了.一般来说,可以使用CSSposition属性进行布局,或者使用CSSfloat属性布局.前者适合布局首页,因为 ...
- 浅谈新的布局方式-flex
引言: 网页布局在flex出来之前,是由盒模型为底子,float,position,table,百分比来进行布局的,重绘的比较多,影响性能,复杂又不好维护.flex布局,可以简便.完整.响应式地实现各 ...
- CSS弹性盒布局(display:flex)
CSS弹性布局(display:flex) 参考: http://www.runoob.com/w3cnote/flex-grammar.html https://www.jianshu.com/p/ ...
- 弹性布局(Flex布局)整理
一. 弹性布局 一个好的网站都有让用户看上去很舒服的布局,一个网站的布局也会或多或少影响到它的浏览量,看完阮大神的博客,就想把弹性布局整理一下. 在平时的我们常用的布局类型有以下几种: 1.浮动+定 ...
- 布局方式-flex布局
.弹性盒子 .盒子本来就是并列的 .指定宽度即可 <style> .container { width: 800px; height: 200px; display: flex; bord ...
- 前端(八)—— 高级布局:文档流、浮动布局、流式布局、定位布局、flex布局、响应布局
高级布局:文档流.浮动布局.流式布局.定位布局.flex布局.响应布局 一.文档流 1.什么是文档流 将窗体自上而下分成一行一行,块级元素从上至下.行内元素在每行中从左至右的顺序依次排放元素 2.本质 ...
- 关于基本布局之——Flex布局
Flex布局 1.Flex为"Flexible Box"的简称,即为弹性布局,可作用于任何容器上.给div这类块状元素元素设置display:flex或者给span这类内联元素设置 ...
- float布局打破标准流,神助攻clear清浮动
布局是什么?根据功能划分小块,再根据设计稿还原,书写静态页面,然后再在块里面填充内容,完善功能,js施加交互效果.div作为一个容器,独占一行,代码书写习惯从上至下属于标准流,而浮动float的css ...
- 布局之: flex(CSS3新增)
flex 基本概念 flex布局(flex是flexible box的缩写), 也称为弹性盒模型 .将属性和属性值(display:flex; )写在哪个标签样式中,谁就是 容器:它的所有子元素自动成 ...
随机推荐
- Android APK 文件结构
序言 APK(全称:Android application package,Android应用程序包)是Android操作系统使用的一种应用程序包文件格式,用于分发和安装移动应用及中间件. APK 文 ...
- Adobe 构建 IDP 之路的经验与教训
在过去的25年多时间里,我创建了软件组件和分布式框架,建立并领导了相关团队.近几年我致力于推动 Adobe 服务开发.部署和管理系统的开发人员生产力. 抽象陷阱 在云时代早期,Adobe 的每个团队都 ...
- ASP.NET Core 6框架揭秘实例演示[38]:两种不同的限流策略
承载ASP.NET应用的服务器资源总是有限的,短时间内涌入过多的请求可能会瞬间耗尽可用资源并导致宕机.为了解决这个问题,我们需要在服务端设置一个阀门将并发处理的请求数量限制在一个可控的范围,即使会导致 ...
- 01-面试必会-JAVA基础篇
1. Final 有什么用? 展开查看 被 final 修饰的类不可以被继承 被 final 修饰的方法不可以被重写 被 final 修饰的变量不可以被改变, 被 final 修饰不可变的是变量的引用 ...
- vulnhub-xxe靶场通关(xxe漏洞续)
vulnhub-xxe靶场通关(xxe漏洞续) 下面简单介绍一个关于xxe漏洞的一个靶场,靶场来源:https://www.vulnhub.com 这里面有很多的靶场. 靶场环境需要自己下载:http ...
- CAN转PROFINET协议网关 JM-PN-CAN
1 产品功能 捷米特JM-PN-CAN 是自主研发的一款 PROFINET 从站功能的通讯网关.主要功能是将各种 CAN 设备接入到 PROFINET 网络中. 捷米特JM-PN-CAN连接到 ...
- 通用权限系统-Spring-Boot-Starter
Spring-Boot-Starter 自定义Starter 案例一:读取application.yml中的参数 1.创建 1.创建maven工程hello-spring-boot-starter 2 ...
- Git存储
Git还提供了一个贮藏的功能.如果你某个分支开发过程中,这个分支的内容是要在本月月底上线的,但是生产上已经出现了一个重大bug,需要你立马去修复.你在分支开发的内容已经开发一部分了,工作区有内容是不能 ...
- 手写call&apply&bind
在这里对call,apply,bind函数进行简单的封装 封装主要思想:给对象一个临时函数来调用,调用完毕后删除该临时函数对应的属性 call函数封装 function pliCall(fn, obj ...
- 现代C++(Modern C++)基本用法实践:零、概述&测试项目
序言 习惯上,我们把C++11之前的C++语法特性称之为"传统C++(traditional c++)",而把c++11之后的语法特性称之为现代C++(modern c++).有一 ...