Skip to content

Flex 与 Grid 解析

设计初衷:Flex 专为一维布局设计,而 Grid 专为二维布局设计。

核心概念差异:一维 vs 二维

Flex (一维布局)

Flex 处理的是单行单列的布局。虽然通过 flex-wrap: wrap 它可以换行,但本质上它仍然是一条线上的元素在折行。它不知道上一行和下一行元素之间的对齐关系。

  • 核心思想:内容驱动。容器的空间由内部元素的大小和弹性规则(放大、缩小)来决定。
  • 控制维度:主轴 (Main Axis) 和 交叉轴 (Cross Axis)。

Grid (二维布局)

Grid 同时处理的布局。它就像一个真正的表格或者坐标系。

  • 核心思想:布局驱动。先画好网格(骨架),然后再把元素填进去。
  • 控制维度:行 (Rows) 和 列 (Columns)。

Flex 指南

Flex 布局非常灵活,最适合组件内部的细节排版(如导航栏、按钮组、图文列表)。

核心属性

作用于容器 (Container):

  • flex-direction: 主轴方向 (row, column)
  • justify-content: 主轴对齐 (center, space-between, space-around)
  • align-items: 交叉轴对齐 (center, stretch)
  • flex-wrap: 是否换行 (nowrap, wrap)

作用于子元素 (Items):

  • flex-grow: 放大比例(默认 0)
  • flex-shrink: 缩小比例(默认 1)
  • flex-basis: 分配多余空间前占据的主轴空间

🤔 flex: 1的含义?

flex: 1 是 flex-grow、flex-shrink 和 flex-basis 三个属性的简写。

  • flex-grow: 1:定义项目的放大比例。如果存在剩余空间,项目将等比例放大占据这部分空间。(默认值是 0,即有剩余空间也不放大)。

  • flex-shrink: 1:定义项目的缩小比例。如果空间不足,项目将按比例缩小。(默认值是 1,即空间不足时大家一起缩小)。

  • flex-basis: 0%:定义了在分配多余空间之前,项目占据的主轴空间。设置为 0% 意味着项目本身的原始大小不计入计算,剩余空间将被完全平分。(默认值是 auto,即项目本来的大小)。

经典场景

万能的垂直居中

css
.center-container {
    display: flex; 
    justify-content: center; /* 水平居中 (主轴) */
    align-items: center; /* 垂直居中 (交叉轴) */ 
    height: 100vh;
}

Grid 实战指南

Grid 最适合页面的宏观架构(如整个页面的页眉、侧边栏、内容区、页脚的划分)以及复杂的图库排列。

核心属性

作用于容器 (Container):

  • grid-template-columns / rows: 定义网格的轨道宽度/高度。

  • gap (grid-gap): 网格线之间的间距。

  • grid-template-areas: 通过命名区域来直观排版。

作用于子元素 (Items):

  • grid-column: 定义元素从哪条垂直网格线开始,到哪条结束 (如 1 / 3)。

  • grid-row: 定义水平网格线的起止。

  • grid-area: 分配到指定的命名区域。

经典场景

直观的圣杯布局 (Holy Grail Layout)

使用 grid-template-areas 可以像画图一样写 CSS 布局,极其优雅:

css
.layout {
    display: grid;
    grid-template-columns: 200px 1fr 200px; /* 左侧200, 中间自适应, 右侧200 */
    grid-template-rows: 60px 1fr 60px; /* 头部60, 内容自适应, 底部60 */

    /* 直接用名字画出布局结构 */
    grid-template-areas:
    "header header header"
    "sidebar content rightbar"
    "footer footer footer";
    height: 100vh;
}

.header {
    grid-area: header;
}

.sidebar {
    grid-area: sidebar;
}

.content {
    grid-area: content;
}

.rightbar {
    grid-area: rightbar;
}

.footer {
    grid-area: footer;
}

真正的响应式网格 (无需媒体查询)

利用 repeat(), auto-fit, 和 minmax(),可以实现极其强大的响应式卡片列表(例如商品列表):

css
.card-grid {
    display: grid;
    gap: 20px;
    /* 魔法代码:卡片最小 250px,最大填满可用空间。空间不够自动换行 */
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

💡 什么时候用 Flex,什么时候用 Grid?

  • 仅仅需要让一组元素排成一排或一列,并且希望它们能自动挤压或拉伸以适应空间时,使用 Flex。

  • 需要精确控制元素在行和列两个维度上的位置,或者你的布局存在明确的“格子”结构时,使用 Grid。

  • 在页面的宏观骨架上使用 Grid,在具体的模块/组件内部(如卡片里的头像和文字对齐)使用 Flexbox。这是现代前端最主流的最佳实践。