返回博客
技术 2025年3月1日 7 分钟阅读 · 1674 字

CSS Grid 与 Flexbox 布局实战完全指南

深入对比 Grid 和 Flexbox 两种布局方案,掌握响应式设计的核心技巧

#CSS #HTML #布局 #响应式设计
本文由 AI 辅助生成,经人工审核发布

在现代 Web 开发中,CSS Grid 和 Flexbox 是两大核心布局系统。它们各自擅长不同的场景,理解它们的差异与协作方式,是构建健壮响应式页面的基础。本文将从原理对比出发,逐步覆盖常见布局模式与响应式技巧。

一、Grid 与 Flexbox 的核心区别

Flexbox 是一维布局系统,旨在沿一条轴(水平或垂直)排列元素;Grid 是二维布局系统,可以同时控制行和列。这并不是说谁更”高级”,而是它们解决的问题维度不同。

对比维度FlexboxGrid
布局维度一维(行或列)二维(行和列同时)
设计思路内容优先,从内容推算尺寸布局优先,先定义网格再放内容
适合场景导航栏、工具栏、卡片行整体页面布局、复杂仪表盘
对齐控制主轴/交叉轴对齐行轨/列轨对齐,更精细
间距处理gap 属性gap / row-gap / column-gap
浏览器支持极佳极佳(IE 11 部分支持)

选择原则

当你需要沿一个方向排列一组元素时,用 Flexbox;当你需要同时控制行列结构时,用 Grid。

一个常见的实践是:用 Grid 搭建页面骨架(header、sidebar、main、footer),用 Flexbox 处理组件内部的一维排列。

二、Flexbox 布局精要

2.1 基本模型

.flex-container {
  display: flex;
  flex-direction: row;        /* row | row-reverse | column | column-reverse */
  justify-content: space-between;  /* 主轴对齐 */
  align-items: center;       /* 交叉轴对齐 */
  flex-wrap: wrap;           /* 允许换行 */
  gap: 16px;
}

.flex-item {
  flex: 1 1 200px;  /* flex-grow | flex-shrink | flex-basis */
}

flex 简写属性是 Flexbox 的灵魂。flex-grow 控制剩余空间分配比例,flex-shrink 控制空间不足时的收缩比例,flex-basis 定义初始尺寸。

2.2 经典导航栏

<nav class="navbar">
  <div class="logo">Brand</div>
  <ul class="nav-links">
    <li><a href="#">首页</a></li>
    <li><a href="#">产品</a></li>
    <li><a href="#">关于</a></li>
  </ul>
  <button class="cta">登录</button>
</nav>
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
  height: 64px;
}

.nav-links {
  display: flex;
  gap: 24px;
  list-style: none;
  margin: 0;
  padding: 0;
}

2.3 flex-grow 与空间分配

/* 三栏:侧边栏固定,中间区域自适应 */
.sidebar  { flex: 0 0 240px; }
.main     { flex: 1 1 0; }      /* 占据所有剩余空间 */
.aside    { flex: 0 0 180px; }

三、Grid 布局精要

3.1 定义网格

.grid-container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;  /* 三列 */
  grid-template-rows: auto 1fr auto;     /* 三行 */
  gap: 20px;
}

fr 单位表示按比例分配剩余空间,类似于 Flexbox 的 flex-grow

3.2 grid-template-areas 语义布局

这是 Grid 最直观的特性,可以用名字描述布局结构:

.page-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr 48px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

3.3 repeat 与 minmax

/* 自适应卡片网格:每列最小 280px,最大占满剩余空间 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

auto-fill 会自动生成尽可能多的列;auto-fit 则会将空列折叠,让现有元素拉伸填满。当卡片数量不足以占满一行时,auto-fit 会让卡片拉伸,而 auto-fill 会保留空位。

四、经典布局模式实现

4.1 圣杯布局

圣杯布局包含 header、footer、以及中间三栏(左定宽、右定宽、中间自适应)。用 Grid 实现非常简洁:

.holy-grail {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "nav    main   aside"
    "footer footer footer";
  min-height: 100vh;
}

.header { grid-area: header; }
.nav    { grid-area: nav; }
.main   { grid-area: main; }
.aside  { grid-area: aside; }
.footer { grid-area: footer; }

4.2 双飞翼布局

双飞翼布局与圣杯布局的目标相同,但通过在内容区嵌套一个内层容器来避免定位问题。用现代 CSS 实现:

.double-wing {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
}

.double-wing .center {
  grid-column: 1 / -1;       /* 跨越所有列 */
  order: 2;
}

.double-wing .left   { order: 1; }
.double-wing .right  { order: 3; }

4.3 瀑布流布局

纯 CSS 实现瀑布流,Grid 的 masonry 值是未来方向(目前 Chrome 已开始支持),当下可用 column-count 方案:

/* 方案一:CSS Multi-column(当下可用) */
.masonry {
  column-count: 3;
  column-gap: 20px;
}

.masonry .item {
  break-inside: avoid;   /* 防止内容跨列断裂 */
  margin-bottom: 20px;
}

/* 方案二:Grid Masonry(实验性) */
.masonry-future {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;  /* 未来标准 */
  gap: 20px;
}

五、响应式断点设计

5.1 常用断点

断点名称宽度范围典型设备
xs< 640px手机竖屏
sm640px - 768px手机横屏
md768px - 1024px平板
lg1024px - 1280px小屏笔记本
xl> 1280px桌面显示器

5.2 移动优先的断点写法

/* 默认移动端:单列 */
.responsive-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

/* 平板:两列 */
@media (min-width: 768px) {
  .responsive-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* 桌面:三列 */
@media (min-width: 1024px) {
  .responsive-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
  }
}

5.3 响应式导航栏切换

/* 移动端:垂直堆叠 */
.navbar {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* 桌面端:水平排列 */
@media (min-width: 768px) {
  .navbar {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
}

六、容器查询:响应式的新范式

媒体查询基于视口宽度,而容器查询基于父容器宽度,使得组件级响应式成为可能。

6.1 基本用法

/* 1. 定义容器 */
.card-container {
  container-type: inline-size;
  /* 或使用简写 */
  container: sidebar / inline-size;
}

/* 2. 根据容器宽度响应 */
@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 120px 1fr;
    gap: 16px;
  }
}

@container (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

6.2 容器查询的优势

同一个卡片组件可以被放在侧边栏(窄)或主内容区(宽),它会根据自身容器尺寸自动调整布局,而无需关心页面整体的视口大小。这让真正可复用的组件系统成为现实。

<!-- 同一个组件,不同容器中表现不同 -->
<aside class="sidebar">
  <article class="card">...</article>  <!-- 窄容器,垂直布局 -->
</aside>

<main class="content">
  <article class="card">...</article>  <!-- 宽容器,水平布局 -->
</main>

七、Grid 与 Flexbox 的协作

实际项目中,两者经常搭配使用。典型模式:

/* Grid 做整体骨架 */
.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 56px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main";
  height: 100vh;
}

/* Flexbox 做组件内部布局 */
.header {
  grid-area: header;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
}

.main {
  grid-area: main;
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 20px;
  align-content: flex-start;
}

总结

场景推荐方案
页面整体骨架Grid
导航栏、工具栏Flexbox
卡片网格Grid + auto-fit
居中单个元素Flexbox
复杂仪表盘Grid
组件内部排列Flexbox
响应式组件容器查询

掌握 Grid 和 Flexbox 的关键不在于背诵属性,而在于理解它们的设计哲学:Grid 是从外向内——先定义网格结构,再放入内容;Flexbox 是从内向外——从内容出发,让容器适应。两者结合,再加上容器查询,几乎可以应对所有现代布局需求。