现代 CSS 布局技巧:Grid、Flexbox 与 Container Queries

布局工具的选择

现代 CSS 提供了三种强大的布局工具。选择哪种取决于你的布局需求:

Flexbox 进阶技巧

大多数人知道 Flexbox 的基础用法,但这些技巧能让你的布局更灵活。

完美的居中方案

/* 万能居中 */
.center-everything {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* 文本和行内元素的垂直居中 */
.card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
}

/* 圣杯布局:固定侧边栏 + 自适应主内容 */
.layout {
  display: flex;
  min-height: 100vh;
}
.sidebar { width: 260px; flex-shrink: 0; }
.main { flex: 1; } /* 自动填满剩余空间 */

flex-wrap 与自动换行

/* 响应式标签云 —— 自动换行 */
.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* 底部对齐的卡片列表 */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}
.card {
  flex: 1 1 300px; /* 最小 300px,可增长 */
  display: flex;
  flex-direction: column;
}
.card-footer {
  margin-top: auto; /* 推到底部 */
}

order 属性控制视觉顺序

/* 移动端:内容优先,侧边栏下方 */
@media (max-width: 768px) {
  .layout { flex-direction: column; }
  .main { order: -1; } /* 主内容移到最前面 */
  .sidebar { order: 1; }
}

CSS Grid 实战

Grid 是 CSS 中最强大的布局系统,特别适合构建复杂的页面布局。

自适应网格(Auto-Fit / Auto-Fill)

/* 自动适应列数的卡片网格 */
.auto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
}

/* auto-fit vs auto-fill 的区别:
   auto-fit: 空轨道会被折叠,卡片会自动拉伸填满
   auto-fill: 空轨道保留,卡片保持原始大小 */

命名区域布局

/* 用命名区域定义页面布局 —— 直观且易维护 */
.page-layout {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
  grid-template-columns: 240px 1fr 200px;
  grid-template-rows: 64px 1fr auto;
  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: 1024px) {
  .page-layout {
    grid-template-areas:
      "header  header"
      "sidebar content"
      "footer  footer";
    grid-template-columns: 200px 1fr;
  }
  .aside { display: none; }
}

@media (max-width: 768px) {
  .page-layout {
    grid-template-areas:
      "header"
      "content"
      "footer";
    grid-template-columns: 1fr;
  }
  .sidebar { display: none; }
}

Subgrid —— 子元素对齐父网格

/* 卡片内容对齐:标题、描述、按钮在不同卡片间对齐 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

.card {
  display: grid;
  grid-template-rows: subgrid; /* 继承父网格的行定义 */
  grid-row: span 3; /* 占 3 行:标题、描述、按钮 */
}

/* 确保所有卡片的标题区域等高,描述区域等高,按钮底部对齐 */

Container Queries —— 组件级响应式

传统的 @media 查询基于视口宽度,但组件可能被放在不同宽度的容器中。Container Queries 让组件根据自身容器的尺寸来调整样式。

/* 第一步:声明容器 */
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

/* 第二步:基于容器宽度写样式 */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 1.5rem;
  }
  .card-image {
    aspect-ratio: 1;
    border-radius: 12px 0 0 12px;
  }
}

@container card (min-width: 600px) {
  .card {
    grid-template-columns: 240px 1fr;
    padding: 2rem;
  }
  .card-title {
    font-size: 1.5rem;
  }
}

@container card (max-width: 399px) {
  .card {
    padding: 1rem;
  }
  .card-title {
    font-size: 1rem;
  }
}

Container Query 单位

/* 容器相对单位 */
.card-title {
  /* cqi = 容器内联尺寸的 1% */
  font-size: clamp(1rem, 4cqi, 2rem);

  /* cqb = 容器块尺寸的 1% */
  line-height: clamp(1.4, 5cqb, 1.8);
}

/* 实用场景:仪表盘小组件在不同宽度下自动调整 */
.stat-card {
  container-type: inline-size;
}
.stat-value {
  font-size: clamp(1.5rem, 8cqi, 3rem);
}
.stat-label {
  font-size: clamp(0.75rem, 3cqi, 1rem);
}

实用布局模式合集

等高卡片布局

/* Grid 方案:天然等高 */
.equal-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.5rem;
  align-items: start;
}

/* Flex 方案:通过 stretch 实现 */
.equal-cards-flex {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}
.equal-cards-flex > * {
  flex: 1 1 250px;
  align-self: stretch;
}

粘性 Footer 布局

/* Grid 方案 */
body {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

/* Flex 方案 */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
main { flex: 1; }

/* 最现代方案 */
body {
  min-height: 100vh;
  min-height: 100dvh; /* 动态视口高度,处理移动端地址栏 */
  display: grid;
  grid-template-rows: auto 1fr auto;
}

全宽横幅中的居中内容

/* 不需要额外的 wrapper div */
.hero-section {
  display: grid;
  grid-template-columns:
    1fr
    min(90%, 1200px)
    1fr;
}

.hero-section > * {
  grid-column: 2;
}

/* 全宽背景但内容居中 —— 直接把背景设在 section 上 */
.hero-section > .full-bleed {
  grid-column: 1 / -1; /* 占满所有列 */
}

CSS Grid vs Flexbox 选择指南

场景推荐原因
导航栏Flexbox一维水平排列,对齐简单
页面整体布局Grid二维布局,区域定义清晰
卡片网格Gridauto-fit 自动列数,天然等高
表单标签+输入框Grid对齐标签和输入框的宽度
居中单个元素Flexbox两行代码搞定
瀑布流/PinterestGridgrid-row: span N 实现不等高
按钮组Flexbox间距和对齐灵活

总结

现代 CSS 布局已经非常强大,Grid 和 Flexbox 的组合可以覆盖几乎所有布局需求。Container Queries 的出现更是让组件级响应式成为现实。建议: