Flex布局和Grid布局详解
Flex布局和Grid布局详解
在前端样式编写中,Flex 布局早已成为日常开发的“标配”。无论是 display: flex 还是 display: grid,它们都为我们提供了强大的自适应能力和灵活的布局方式。但如果对 Flex 的理解仅停留在 align-items、justify-content 这些常见属性的简单使用,那么在面对复杂布局或一些“看似奇怪”的样式问题时,往往会陷入困惑:为什么设置了 height 却不生效?为什么元素没有按预期填满空间?又或者,什么时候该用 Grid,什么时候该用 Flex?
事实上,Flex 和 Grid 并不仅仅是“用来排版”的工具,它们背后各自有一套完整的布局模型和计算规则。理解这些规则,不仅能帮你写出更简洁、可控的样式,还能让你在调试布局问题时少走很多弯路。本文将系统梳理 display: flex 与 display: grid 的核心原理、关键差异,以及它们在不同布局需求下的最佳使用方式,帮助你真正掌握现代 CSS 布局的底层逻辑。
Flex弹性盒子布局
display: flex ,通常被称为flexbox。它是一种一维的布局模型。“一维”是指一个flexbox 一次只能处理一个维度上的元素布局,它只能控制flex-direction设置的主轴方向的元素布局,即行或者列。
相比下display: grid,网格布局就可以同时处理行和列上的布局,因此网格布局也被称为二维布局。
下面本文将从实际开发的场景出发,让你实际感受一下这两个布局的直观差别:
在使用 flex 布局的时候,很容易遇到元素换行后,换行位置出现很大的空余截断的场景,如下图所示。出现这种情况的原因在于,flex布局并不能精准控制行和列的显示,当屏幕不足以放下下一个元素的时候,flex会直接将下一个元素放到下一列 或 行显示(这个却决于你的主轴设置)
同样的场景下,grid 布局就显得更为合理,如下图。
鼠标放在元素上,仔细观察,我们就能发现 grid 布局的精妙之处,你可以通过设置grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) 实现列的自适应扩展,多个块共同划分多余的内容,这样在视觉呈现上使其更加合理。除此之外,你还可以通过设置grid-template-row: 来控制行的排列,而这就是所谓的二维布局。
Flex 元素上的三个基本属性
一个容器的 display 属性值为 flex 或者 inline-flex,容器中的直系子元素就是 flex 元素。flex 容器中的所有 flex 元素不会在主轴拉伸,但是可以缩小。这也就是为什么,在不设置flex-wrap: wrap,子元素未设置flex-shrink 和 flex-basis,且容器的在主轴线上大小固定时,子元素的大小会随着子元素数量的增多而缩小的原因。
为了更好的控制 flex 元素,CSS 引入了三个属性:flex-grow、flex-shrink、flex-basis。这几个属性本上就是改变了 flex 容器的"可用空间"行为,每个属性都定义了子元素该如何去利用可用空间,如何在空间不足时去分配空间——flex 容器里除了元素所占的空间以外的富余空间就是可用空间。下面开始讲解这三个属性,基于主轴为row的场景进行举例讲解。
-
flex-basis:定义了 flex 元素的初始空间大小。auto(默认):当flex-basis: auto时,浏览器会先检测这个元素是否具有确定的尺寸,如果元素设置了 width 为100px,则约等于flex-basis: 100px。 如果没有设定尺寸,则flex-basis的值采用元素的内容尺寸,这也就是为什么我们不设置元素大小的时候,只为父元素设置display: flex时,内容多的元素会更大。0(特殊情况):flex-basis: 0是 Flex 布局里一个非常关键但也最容易被忽略的点,其表示:**元素的初始尺寸按 0 计算,完全忽略内容大小,只按剩余空间分配。**这也意味着所有子元素都在同一起跑线,其能分配的内容大小取决于flex-grow的大小。100px(固定值)
-
flex-grow:定义了当容器有剩余空间时,这个元素“愿意放大”的比例,值**>= 0**,默认为1。eg: 一个 flex 容器内有a、b两个子元素,a元素只设置了flex-grow: 2,b元素未设置任何属性,此时a元素的大小为容器width * (2/1+2)。 -
flex-shrink: 与flex-grow相反,该属性是作用于当容器空间不能满足所有子元素的flex-basis时,每个元素“愿意被挤压”的程度。值**>= 0,默认为1。计算公式为:(所有子元素基础宽度之和 - 容器宽度) * (当前子元素的flex-shrink值 / 所有子元素的flex-shrink值之和),0特殊**意味着不参与布局。
这个三个属性缩写:flex: <flex-grow> <flex-shrink> <flex-basis>, 常见 flex: 1 等价于 flex: 1 1 0,flex: 2 等价于 flex: 2 1 0
Flex 容器的对齐规则
align-items 属性可以使元素在交叉轴(与主轴垂直的方向)方向对齐。
justify-content属性用来使元素在主轴方向上对齐
Flex 元素独立的对齐规则
除了对容器整体对齐规则做设置外,我们还可以对 flex 容器内指定的元素进行独立调整。
align-self 调整元素在交叉轴上的对齐方式,覆盖容器的align-items的属性,值与其相同。注意:任何 flex元素的交叉轴方向 margin 值设置为 auto,则会忽略 align-self。
Grid 网格布局
display: grid,称为CSS 网格布局。它与flex弹性布局的区别除了前面所说的一维和二维的区别外,还有一个关键的区别:在网格布局中,你需要在容器上设置大部分尺寸规范,设置轨道然后将元素放入其中。在弹性盒子中,虽然你创建了弹性容器并设置了该级别的方向,但是对元素大小的任何控制都需要在元素本身之上进行。从grid的基本属性设置grid-template-columns和grid-template-rows就可以看出。
基本概念
网格布局中最关键的就是理解网格的行和列的意义,如下图。行和列交叉的区域叫“单元格”,即元素。
在 Grid 布局里,定位是基于 网格线(grid line) 而不是网格单元。
布局结构:
| 1 | 2 | 3 |
网格线编号:
1 2 3 4
|---|---|---|
3列会有 4条网格线,元素通过 起始线 → 结束线 来确定位置。
属性介绍
下列的xx-columns与xx-rows的区别只是对应轴线的不同。
grid-template-columns 属性, grid-template-rows 属性
100px 100px 100px:指定了三个元素大小,每个元素100px。这是通过为每个元素设置固定的大小的px。max-content:表示元素按照内容能够达到的最大尺寸进行布局,不会因为容器限制而主动换行或收缩。min-content:表示元素在不溢出的情况下可以缩小到的最小尺寸。fit-content():表示元素宽度根据内容自适应,但不会超过容器限制。举例:grid-template-columns: fit-content(300px);含义:列宽 = min(max-content, 300px)1fr:用于表示比例关系,两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。与绝对长度单位结合使用,会非常方便如:150px 1fr 2fr表示第一列的宽度为150px,第二列的宽度是第三列的一半。minmax(): 产生一个长度范围,表示长度就在这个范围之中。auto:表示由浏览器自己决定长度。repeat(): 接收两个参数,第一个参数是重复元素的个数,第二个参数是重复元素的大小,与前面介绍的参数一致- 第一个参数 :
1(具体数字):表示固定的重复个数。auto-fill: 表示自动填充,有时,单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,此时可以使用这个参数。auto-fit:行为与auto-fill相同,区别在于auto-fill不会保留空列,即如果容器一行能放5个元素,现在只有3个元素,此时auto-fill的行为会呈现[ item ][ item ][ item ][ ][ ],auto-fit会将剩余空间分配给这三个元素,呈现[ item ][ item ][ item ]。
- 第一个参数 :
gap 属性
grid-row-gap:设置行间距,grid-row-gap: 20px;grid-column-gap: 设置列间距,grid-column-gap: 20px;grid-gap: <grid-row-gap> <grid-column-gap>:grid-gap: 20px 20px;
grid-auto-flow 属性
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行。
grid-auto-flow: column; 默认值是row,即"先行后列"。也可以将它设成column,变成"先列后行"。
grid-auto-flow: row dense; 加上dense表示尽量填满空格。
grid-column 属性, grid-row 属性
grid-column: start / end;表示:从第 start 条列线,到第 end 条列线。
.item {
grid-column: 1 / 3;
}
效果:
|------|-----|-------|
| column1 |column3|
grid-auto-columns属性,grid-auto-rows属性
当网格项目被放到一个没有显式定义的行或列时,浏览器会自动创建新的行或列,这些自动生成的轨道尺寸就由这两个属性决定。
例如:
.container {
display: grid;
grid-template-columns: 200px 200px;
}
这里只定义了 2列,如果子元素被放到第三列:
.item {
grid-column: 3;
}
此时浏览器会 自动创建一列,这个就是叫隐式网格列,它的宽度由:grid-auto-columns控制。
设置格式:grid-auto-columns: 100px;
网格布局元素独立的对齐规则
除了Flex元素的align-self外,网格布局中的块元素还支持justify-self调整元素在主轴上的对齐方式,覆盖容器的justify-items的属性,值与其相同。
什么时候用 Flex?什么时候用 Grid?
Flex: 横向排列(导航栏)、垂直居中、按比例分配空间、简单的排版
Grid: 卡片布局、后台表格布局、仪表盘、复杂排版
参考资料
https://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Guides/Flexible_box_layout
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)