普通视图

发现新文章,点击刷新页面。
今天 — 2026年4月13日首页

Flex + Grid 混合布局指南

作者 小霍同学
2026年4月13日 09:04

Flex + Grid 混合布局指南

在现代前端开发中,Flex 和 Grid 并不是非此即彼的选择,而是一对强大的组合拳。Flex 擅长一维排列(行或列),Grid 擅长二维布局(行与列同时控制)。混合使用它们,可以同时获得两种布局模型的优点:用 Grid 搭建页面的宏观骨架,用 Flexbox 处理组件内部的微观对齐。

Flex 与 Grid 的核心差异

维度 Flex Grid
维度 一维(行 列) 二维(行 列同时控制)
内容驱动 项目沿主轴分布,由内容撑开 轨道由容器定义,项目放置其中
对齐能力 主轴/交叉轴对齐,强大且灵活 单元格内对齐 + 整个网格对齐
典型用途 导航栏、列表、卡片内元素 整体页面布局、相册网格、表单

一句话总结:

  • 需要精确控制行和列的位置关系 → Grid
  • 需要沿着一个方向灵活排列,或处理未知数量的项目 → Flex

快速决策:何时用 Flex,何时用 Grid

优先使用 Grid 的场景

  • 整体页面结构(header, main, sidebar, footer)
  • 复杂的二维网格(如仪表盘、作品集、图库)
  • 需要显式控制重叠区域(grid-template-areas
  • 轨道尺寸需要基于比例(fr)和内容(minmax())配合

优先使用 Flexbox 的场景

  • 导航栏、工具栏、按钮组
  • 列表项内部(头像 + 文本 + 操作按钮)
  • 居中对齐(特别是垂直居中)需求强烈
  • 项目数量不固定,需要自动换行(flex-wrap
  • 顺序重排(order)的轻量需求

混合策略:宏观 Grid + 微观 Flex

这是最常用的模式:用 Grid 划分大区域,用 Flexbox 安排每个区域内部的内容

┌─────────────────────────────────────┐
│  Header (Grid 区域)                  │
│  └─ 内部用 Flex 排列 Logo + 导航菜单   │
├───────────┬─────────────────────────┤
│ Sidebar   │ Main (Grid 区域)         │
│ (Grid)    │ └─ 卡片列表用 Grid        │
│ └─ 内部用 │   每个卡片内部用 Flex      │
│   Flex 列 │   排列头像/标题/按钮       │
│   表导航  │                          │
├───────────┴─────────────────────────┤
│  Footer (Grid 区域)                  │
│  └─ 内部用 Flex 排列版权与链接         │
└─────────────────────────────────────┘

混合布局的四种实用模式

模式一:Grid 容器内使用 Flex 项目

场景:Grid 定义了宏观区域(如页眉、侧边栏),每个区域内需要水平或垂直排列元素。

<div class="page">
  <header class="header"> ... </header>
  <aside class="sidebar"> ... </aside>
  <main class="content"> ... </main>
  <footer class="footer"> ... </footer>
</div>
.page {
  display: grid;
  grid-template-areas: 
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-columns: 250px 1fr;
  gap: 20px;
}

.header {
  grid-area: header;
  display: flex;           /* 内部使用 Flexbox */
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
}

.sidebar {
  grid-area: sidebar;
  display: flex;
  flex-direction: column;  /* 垂直排列导航项 */
  gap: 0.5rem;
}

.footer {
  grid-area: footer;
  display: flex;
  justify-content: center;
  gap: 2rem;
}

模式二:Flex 容器内使用 Grid 项目

场景:外层是 Flex 排列的卡片容器,但每个卡片内部是二维网格布局(如图片区、标题区、描述区)。

<div class="card-list">
  <div class="card">
    <div class="card-image">...</div>
    <div class="card-title">...</div>
    <div class="card-desc">...</div>
    <div class="card-footer">...</div>
  </div>
  <!-- 更多卡片 -->
</div>
.card-list {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  flex: 280px;              /* 简写,等价于 flex: 1 1 280px */
  display: grid;            /* 卡片内部使用 Grid */
  grid-template-rows: auto auto 1fr auto;
  gap: 12px;
  background: #f5f5f5;
  padding: 1rem;
}

.card-image { grid-row: 1; }
.card-title { grid-row: 2; }
.card-desc { grid-row: 3; }
.card-footer { 
  grid-row: 4;
  display: flex;            /* 甚至可以再嵌套 Flex */
  justify-content: flex-end;
}

模式三:响应式切换布局模式(Grid ↔ Flex)

场景:在宽屏时使用 Grid 展示多列,在窄屏时改为 Flex 垂直堆叠。

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

@media (max-width: 768px) {
  .container {
    display: flex;
    flex-direction: column;
    gap: 20px;
  }
  /* 关键:Flex 子项默认不拉伸宽度,需显式设置 */
  .container > * {
    width: 100%;
  }
}

注意:从 Grid 切换到 Flex 时,Grid 子项默认会拉伸填满列宽,而 Flex 子项默认按内容宽度显示。添加 width: 100% 可使其填满父容器。

模式四:利用 Flex 对齐能力简化 Grid 内部对齐

Grid 虽然提供了 place-items / place-self,但对于单行/单列的简单排列,Flex 往往更简洁。

需求:在 Grid 单元格内让一个按钮水平居中且底部对齐。

.grid-cell {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
}

相比之下,如果只用 Grid 属性,需要写 align-self: end; justify-self: center,且无法轻松实现垂直方向上的多个元素排列(如按钮上方还有文本)。Flexbox 更自然。

最佳实践与注意事项

推荐做法

  1. 从宏观到微观:先用 Grid 设计整体页面结构,再用 Flexbox 处理局部细节。
  2. 利用 gap 统一间距:Grid 和 Flex 都支持 gap,尽量使用而非 margin 来避免外边距折叠问题。
  3. 响应式优先使用 auto-fill / auto-fit:在 Grid 中结合 minmax() 创建弹性网格,减少媒体查询。
  4. 避免过度嵌套:能用一个 Grid 实现二维布局,就不要在外面再套一层 Flex。
  5. 善用 flex: 1 填充剩余空间:在 Grid 单元格内,如果需要某个 Flex 子项占满剩余高度,使用 flex: 1

常见陷阱及解决方案

  • Grid 子项作为 Flex 容器时,min-width: auto 可能导致内容溢出 解决方案:给该 Flex 容器设置 min-width: 0overflow: hidden,允许内容收缩到比默认最小宽度更小。

    .grid-item {
      display: flex;
      min-width: 0;   /* 防止长单词或图片撑开父级 */
    }
    
  • flex 属性在 Grid 项目上无效 Grid 项目的尺寸由 grid-template-columns/rows 决定,设置 flex: 1 不会影响其在网格中的大小。如果希望 Grid 项目内部有弹性填充,请在该项目内部使用 Flex 容器。

  • gap 在 Grid 与 Flex 中的行为差异

    • Grid:gap 在轨道之间添加间隔,间隔尺寸先于 fr 分配扣除,剩余空间再按比例分配。
    • Flex:gap 仅在项目之间添加间隔,不影响主轴对齐(如 space-between 会忽略最后一个 gap)。
  • Flex 换行与 Grid 混用的理解 Grid 容器内的项目默认不会自动换行(除非使用 repeat(auto-fill, ...))。如需类似 Flex 的换行效果,请使用 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))

  • align-self / justify-self 在 Flex 项目中无效 这些属性是 Grid 项目的专用属性,不要错误地应用于 Flex 子项。

兼容性提示

特性 Chrome Firefox Safari Edge IE
Flexbox (无前缀) 29+ 28+ 9+ 12+ 11(部分)
Grid (无前缀) 57+ 52+ 10.1+ 16+ 不支持
gap in Flexbox 84+ 63+ 14.1+ 84+ 不支持
subgrid 117+ 71+ 16+ 117+ 不支持

现状说明gap 在 Flexbox 中的支持现已普及(主流浏览器最新版本均支持),仅需注意 Safari < 14.1 或 iOS < 14.1 的旧设备。subgrid 已得到现代浏览器良好支持,可用于复杂嵌套网格。

对于需要兼容 IE 的项目

  • 不要使用 Grid(或使用降级方案,如 @supports 检测)
  • 完全依赖 Flexbox 配合 float 后备
  • 避免使用 Flexbox 的 gap,改用 margin

推荐使用 Autoprefixer 处理旧版浏览器前缀,并在 Grid 布局中提供简单的 Flex 后备:

.container {
  display: flex;           /* 后备 */
  flex-direction: column;
}

@supports (display: grid) {
  .container {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
}
昨天以前首页

CSS Grid 布局参考表

作者 小霍同学
2026年4月10日 11:04

CSS Grid 布局参考表

容器属性(作用在父元素)

属性 可选值 默认值 说明
display grid inline-grid 定义块级或行内级网格容器
grid-template-columns 长度 / 百分比 / fr / auto / minmax() / repeat() none 定义列宽(数量和尺寸),如 200px 1fr 2fr
grid-template-rows 同上 none 定义行高(数量和尺寸),如 100px auto 1fr
grid-template-areas 字符串组成的矩阵,用 . 表示空单元格 none 通过命名区域定义布局,如 "header header" "sidebar main"
gap row-gap column-gap 长度值(20px1rem 0 行间距 / 列间距。gap 为简写,先行后列
justify-items start / end / center / stretch stretch 所有项目在单元格内的水平对齐(行轴)
align-items start / end / center / stretch stretch 所有项目在单元格内的垂直对齐(列轴)
place-items <align-items> <justify-items> stretch stretch 简写,先垂直后水平,如 center center
justify-content start / end / center / stretch / space-between / space-around / space-evenly start 整个网格在容器内的水平对齐(网格总宽 < 容器时生效)
align-content 同上 start 整个网格在容器内的垂直对齐(网格总高 < 容器时生效)
place-content <align-content> <justify-content> start start 简写,先垂直后水平
grid-auto-columns 长度 / 百分比 / fr / minmax() auto 隐式创建的列的尺寸
grid-auto-rows 同上 auto 隐式创建的行的尺寸
grid-auto-flow row / column / row dense / column dense row 自动布局的排列方向及是否“紧密”填充

项目属性(作用在直接子元素)

属性 可选值 默认值 说明
grid-column start / end span n start / span n auto / auto 项目占用的列范围,例:2 / 4span 22 / span 2
grid-row 同上 auto / auto 项目占用的行范围
grid-area <row-start> / <col-start> / <row-end> / <col-end> 或区域名称 auto 位置简写或引用 grid-template-areas 定义的名称
justify-self start / end / center / stretch stretch 单个项目在单元格内的水平对齐(覆盖容器 justify-items
align-self start / end / center / stretch stretch 单个项目在单元格内的垂直对齐(覆盖容器 align-items
place-self <align-self> <justify-self> stretch stretch 简写,先垂直后水平,如 center end

常用函数与关键字速查

函数/关键字 语法示例 说明
fr 1fr2fr 剩余空间分数单位,类似 Flexbox 的 flex-grow
minmax() minmax(100px, 1fr) 定义尺寸范围(最小,最大),用于响应式轨道
repeat() repeat(3, 1fr) 简化重复轨道定义,可嵌套 minmax()
auto-fill repeat(auto-fill, 200px) 尽可能多地放置轨道(不拉伸),空轨道保留空间
auto-fit repeat(auto-fit, 200px) 放置轨道后拉伸现有轨道填满容器,空轨道折叠
span grid-column: span 2 跨越指定数量的轨道,不指定起始线

对齐方式速查(区分容器级与项目级)

作用对象 水平对齐属性 垂直对齐属性 简写
所有项目在单元格内 justify-items align-items place-items
单个项目在单元格内 justify-self align-self place-self
整个网格在容器内 justify-content align-content place-content

关键点

  • justify-* 控制行轴(水平),align-* 控制列轴(垂直)。
  • *-items / *-self 控制项目在单元格内的位置,*-content 控制整个网格在容器内的位置。

隐式网格 vs 显式网格

类型 定义属性 说明
显式网格 grid-template-rows grid-template-columns 开发者明确指定的行/列轨道
隐式网格 grid-auto-rows grid-auto-columns 当项目超出显式范围时自动生成的额外轨道,尺寸由 grid-auto-* 决定

触发隐式网格的常见情况:

  • 使用 grid-row: 4 但显式只定义了 3 行。
  • 自动布局的项目数量多于显式网格单元格数(配合 grid-auto-flow)。

浏览器兼容性简表

浏览器 最低支持版本 备注
Chrome 57+ 完全支持
Firefox 52+ 完全支持
Safari 10.1+ 完全支持
Edge 16+ 完全支持
IE 10 / 11 部分支持(旧语法 -ms- 不推荐用于现代项目,存在大量 bug
❌
❌