前端开发2026-03-17 13 分钟

CSS 现代布局完全指南:Flexbox 和 Grid 从入门到实战

别再用 float 和 margin hack 了。2026 年了,是时候彻底掌握现代 CSS 布局了。

我见过太多前端开发者(包括曾经的我)写 CSS 布局的方式是:先 display: flex,然后开始疯狂加 marginpaddingposition: absolute,直到「看起来对了」为止。这种写法的问题是——换个屏幕尺寸就全崩了。

这篇文章不是属性查询手册(那种东西 MDN 更好),我想做的是:用真实的布局场景,把 Flexbox 和 Grid 的核心思维模型讲清楚。掌握了思维模型,你遇到任何布局需求都能快速选择正确的方案。

1. 核心区别:一维 vs 二维

这是理解 Flexbox 和 Grid 最重要的一句话:

Flexbox = 一维布局系统
  ↓ 在一个方向上排列元素(一行或一列)
  ↓ 适合:导航栏、按钮组、卡片行、工具栏

Grid = 二维布局系统
  ↓ 同时控制行和列
  ↓ 适合:页面整体布局、仪表盘、表单、图片画廊

选择原则

内容优先 → Flexbox:你不知道会有多少个子元素,让内容决定布局(比如标签列表、评论区)。
布局优先 → Grid:你知道页面的布局结构(几行几列),让布局容纳内容(比如管理后台、landing page)。

实际项目中,两者经常混用:Grid 做页面大框架,Flexbox 处理每个区域内部的排列。

2. Flexbox 进阶:超越 justify-content

flex-grow / flex-shrink / flex-basis

大多数人只用 flex: 1,但不知道它是三个属性的简写。理解这三个属性,你就能精确控制元素如何分配空间。

flex: <flex-grow> <flex-shrink> <flex-basis>

flex-basis   → 元素在分配剩余空间之前的「基准尺寸」
flex-grow    → 有多余空间时,按什么比例分配
flex-shrink  → 空间不够时,按什么比例收缩

// flex: 1 等于 flex: 1 1 0%
// 意思是:基准尺寸 0,等比例伸展和收缩

// 实用写法
.sidebar  { flex: 0 0 280px }  // 固定 280px,不伸展不收缩
.content  { flex: 1 1 0% }     // 占满剩余空间
.aside    { flex: 0 0 200px }  // 固定 200px

实战:经典导航栏

/* Logo 在左,菜单在中间,按钮在右 */
.navbar {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.logo      { flex: 0 0 auto; }         /* 固有尺寸 */
.nav-links { flex: 1; text-align: center; } /* 占满中间 */
.actions   { flex: 0 0 auto; }         /* 固有尺寸 */

/* 为什么不用 margin-left: auto?
   用 flex-grow 更语义化,而且在 RTL 语言下自动适配 */

实战:flex-wrap 做响应式卡片

/* 不用媒体查询就能实现响应式卡片布局! */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.card {
  flex: 1 1 300px;  /* 最小 300px,多余空间等比例分配 */
  /* 大屏:一行 3-4 张卡片 */
  /* 小屏:自动换行,可能一行 1-2 张 */
}

/* 关键技巧:用 max-width 防止单独一行时卡片拉太宽 */
.card {
  flex: 1 1 300px;
  max-width: 400px;
}

3. CSS Grid 进阶:从 fr 到 grid-template-areas

fr 单位:灵活的比例分配

/* fr = fraction(比例份额)*/
.grid {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  /* 总共 4 份,左右各 1 份,中间 2 份 */
  /* 比百分比好的地方:fr 会自动减去 gap */
  gap: 1rem;
}

/* 混合使用固定值和 fr */
.layout {
  grid-template-columns: 280px 1fr;
  /* 左侧固定 280px 的侧边栏,右侧自适应 */
}

/* 经典 12 列栅格 */
.grid-12 {
  grid-template-columns: repeat(12, 1fr);
}
.col-span-4 { grid-column: span 4; }
.col-span-8 { grid-column: span 8; }

grid-template-areas:可视化布局

这是 CSS Grid 最酷的特性——你可以用「ASCII art」的方式定义布局!

/* 经典后台管理布局 */
.dashboard {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
  grid-template-columns: 240px 1fr 200px;
  grid-template-rows: 60px 1fr 40px;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside   { grid-area: aside; }
.footer  { grid-area: footer; }

/* 响应式:小屏隐藏侧边栏 */
@media (max-width: 768px) {
  .dashboard {
    grid-template-areas:
      "header"
      "content"
      "footer";
    grid-template-columns: 1fr;
  }
  .sidebar, .aside { display: none; }
}

为什么 grid-template-areas 好用?

1. 可读性极强:一看就知道布局结构,不需要在脑子里算行列号。
2. 调整布局只需改一个地方:想把 sidebar 移到右边?改一下 areas 字符串就行,子元素的 CSS 完全不用动。
3. 天然防错:每一行必须有相同数量的区域名,否则 CSS 会忽略整个声明——这比错误地设置行列号好得多。

4. 终极响应式:auto-fill + minmax

如果你只记一个 Grid 技巧,记这个——不用写任何媒体查询就能实现完美响应式卡片布局:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

/* 这一行代码做了什么:
   - auto-fill:自动填充尽可能多的列
   - minmax(280px, 1fr):每列最小 280px,最大等比例分配
   - 大屏:4-5 列  |  中屏:2-3 列  |  小屏:1 列
   - 完全自适应,不需要任何媒体查询! */

auto-fill vs auto-fit

auto-fill:即使没有足够的元素,也保留空的列轨道。
auto-fit:把空的列轨道折叠为 0,让现有元素拉伸填满整行。

大多数情况用 auto-fill 就对了。只有当你希望少量元素撑满整行时,才用 auto-fit

5. Subgrid:终结「对不齐」的痛

卡片列表中最常见的问题:每张卡片的标题长度不同,导致描述文字的起始位置参差不齐。subgrid 就是用来解决这个问题的。

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

.card {
  display: grid;
  grid-template-rows: subgrid;  /* 继承父级的行轨道 */
  grid-row: span 3;             /* 每张卡片占 3 行 */
  /* 第 1 行:标题
     第 2 行:描述
     第 3 行:按钮
     所有卡片的这三个区域会自动对齐! */
}

/* 之前的 hack 做法:
   .title { min-height: 60px }    ← 写死高度,不优雅
   .description { flex: 1 }       ← Flex 能拉伸但不能跨卡片对齐
   subgrid 是真正的解决方案 */

subgrid 已经被所有现代浏览器支持(Chrome 117+, Firefox 71+, Safari 16+),2026 年可以放心使用。

6. 实战速查:常见布局一行搞定

/* 1. 水平垂直居中 */
.center {
  display: grid;
  place-items: center;
}

/* 2. 粘性页脚(footer 始终在底部) */
body {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}
/* header = auto, main = 1fr(填满中间), footer = auto */

/* 3. 等高列 */
.equal-height {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
}

/* 4. Masonry 瀑布流(实验性) */
.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;  /* Chrome 未支持,Firefox 已支持 */
}

/* 5. 两列表单(label + input 对齐) */
.form {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.75rem 1.5rem;
}
/* 6. 圣杯布局(header + 三栏 + footer)最简写法 */
.holy-grail {
  display: grid;
  grid-template:
    "h h h" auto
    "l m r" 1fr
    "f f f" auto
    / 200px 1fr 200px;
  min-height: 100vh;
}

/* grid-template 是以下三个属性的简写:
   grid-template-areas
   grid-template-rows
   grid-template-columns
   一行搞定,无需三个属性分开写 */

选择指南

场景                        推荐方案
──────────────────────────────────────
导航栏、按钮组、标签栏        Flexbox
卡片列表(数量不定)          Flexbox (wrap) 或 Grid (auto-fill)
页面整体框架                  Grid (template-areas)
仪表盘 / 管理后台             Grid
表单布局                     Grid (两列)
居中一个元素                  Grid (place-items: center)
一行内的水平排列              Flexbox

CSS 布局不再是「碰运气」。Flexbox 管好一维排列,Grid 管好二维结构,两者配合使用,几乎没有实现不了的布局。如果你还在纠结样式框架的选择,推荐看看 Tailwind CSS 使用体验分享