引言

CSS布局技术在过去几年发生了革命性的变化。Flexbox和Grid的出现,让我们能够用更少的代码实现更复杂的布局效果。本文将深入探讨这两种现代布局技术,帮助你掌握它们的精髓并灵活运用于实际项目中。

Flexbox:一维布局的利器

Flexbox 基础概念

Flexbox(弹性盒子)是用于一维布局的强大工具,特别适合处理行或列的布局:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.container {
  display: flex;
  /* 主轴方向 */
  flex-direction: row; /* row | row-reverse | column | column-reverse */

  /* 换行设置 */
  flex-wrap: nowrap; /* nowrap | wrap | wrap-reverse */

  /* 简写属性 */
  flex-flow: row nowrap;
}

主轴与交叉轴对齐

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.container {
  /* 主轴对齐 */
  justify-content: flex-start; /* flex-start | flex-end | center | space-between | space-around | space-evenly */

  /* 交叉轴对齐 */
  align-items: stretch; /* stretch | flex-start | flex-end | center | baseline */

  /* 多行对齐 */
  align-content: stretch; /* stretch | flex-start | flex-end | center | space-between | space-around */
}

Flex 项目的属性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
.item {
  /* 扩展比例 */
  flex-grow: 0;

  /* 收缩比例 */
  flex-shrink: 1;

  /* 基础大小 */
  flex-basis: auto;

  /* 简写属性 */
  flex: 0 1 auto;

  /* 单独对齐 */
  align-self: auto; /* auto | flex-start | flex-end | center | baseline | stretch */

  /* 排序 */
  order: 0;
}

实际应用示例

1. 垂直居中的万能方案

1
2
3
4
5
6
.center-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

2. 导航栏布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
}

.nav-brand {
  flex: 0 0 auto;
}

.nav-links {
  display: flex;
  gap: 1rem;
}

.nav-actions {
  display: flex;
  gap: 0.5rem;
}

3. 等高卡片布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
.card-container {
  display: flex;
  gap: 1rem;
}

.card {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.card-content {
  flex: 1; /* 让所有卡片高度一致 */
}

4. 圣杯布局

1
2
3
4
5
6
7
<div class="holy-grail">
  <header>Header</header>
  <main>Main Content</main>
  <nav>Navigation</nav>
  <aside>Sidebar</aside>
  <footer>Footer</footer>
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.holy-grail {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

header, footer {
  flex: 0 0 auto;
}

.holy-grail-body {
  display: flex;
  flex: 1;
}

main {
  flex: 1;
  order: 2;
}

nav {
  flex: 0 0 200px;
  order: 1;
}

aside {
  flex: 0 0 200px;
  order: 3;
}

CSS Grid:二维布局的革命

Grid 基础概念

Grid布局是专门为二维布局设计的,可以同时控制行和列:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
.grid-container {
  display: grid;

  /* 定义列和行 */
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 100px 200px;

  /* 简写 */
  grid-template:
    "header header header" 60px
    "nav main aside" 1fr
    "footer footer footer" 60px
    / 200px 1fr 200px;

  /* 间距 */
  gap: 20px; /* row-gap column-gap */
}

网格线命名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.grid {
  display: grid;
  grid-template-columns: [left-start] 200px [left-end main-start] 1fr [main-end right-start] 200px [right-end];
  grid-template-rows: [header-start] 60px [header-end content-start] 1fr [content-end footer-start] 60px [footer-end];
}

.item {
  /* 使用命名线 */
  grid-column: main-start / main-end;
  grid-row: content-start / content-end;
}

Grid 区域命名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.grid {
  display: grid;
  grid-template-areas:
    "header header header"
    "nav main aside"
    "footer footer footer";
}

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

自动布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.grid {
  display: grid;
  /* 自动填充 */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  /* 或自动适应 */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

  /* 密集填充 */
  grid-auto-flow: row dense; /* row | column | row dense | column dense */
}

实际应用示例

1. 响应式网格系统

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
.responsive-grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(12, 1fr);
}

.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-12 { grid-column: span 12; }

@media (max-width: 768px) {
  .col-6,
  .col-4,
  .col-3,
  .col-2 {
    grid-column: span 12;
  }
}

2. 图片画廊

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

.gallery-item {
  aspect-ratio: 1;
  object-fit: cover;
}

/* Masonry 风格 */
.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 20px;
  gap: 20px;
}

.masonry-item {
  grid-row: span var(--row-span);
}

3. 复杂的仪表板布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
.dashboard {
  display: grid;
  grid-template-columns: 250px 1fr 300px;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas:
    "header header header"
    "sidebar main aside"
    "footer footer footer";
  min-height: 100vh;
  gap: 20px;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main {
  grid-area: main;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}
.aside { grid-area: aside; }
.footer { grid-area: footer; }

/* 响应式调整 */
@media (max-width: 1024px) {
  .dashboard {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "aside"
      "sidebar"
      "footer";
  }

  .main {
    grid-template-columns: 1fr;
  }
}

Grid 与 Flexbox 的结合使用

典型组合场景

1
2
3
4
5
6
7
8
9
<div class="app">
  <header class="header"></header>
  <div class="main">
    <nav class="nav"></nav>
    <main class="content"></main>
    <aside class="aside"></aside>
  </div>
  <footer class="footer"></footer>
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header, .footer {
  flex: 0 0 auto;
}

.main {
  flex: 1;
  display: grid;
  grid-template-columns: 200px 1fr 250px;
  gap: 20px;
}

.content {
  /* 内部使用 Flexbox */
  display: flex;
  flex-direction: column;
  gap: 20px;
}

实战案例:产品展示页面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<div class="product-page">
  <header class="page-header">
    <div class="header-content">
      <h1>产品展示</h1>
      <div class="filters">
        <!-- 筛选按钮组使用 Flexbox -->
      </div>
    </div>
  </header>

  <div class="page-main">
    <aside class="sidebar">
      <!-- 侧边栏使用 Grid -->
    </aside>

    <main class="product-grid">
      <!-- 产品网格使用 Grid -->
    </main>
  </div>
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
.product-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page-header {
  flex: 0 0 auto;
  padding: 1rem 0;
  border-bottom: 1px solid #eee;
}

.header-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.filters {
  display: flex;
  gap: 1rem;
}

.page-main {
  flex: 1;
  display: grid;
  grid-template-columns: 250px 1fr;
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem 1rem;
  gap: 2rem;
}

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

@media (max-width: 768px) {
  .page-main {
    grid-template-columns: 1fr;
  }

  .header-content {
    flex-direction: column;
    gap: 1rem;
    align-items: flex-start;
  }

  .filters {
    flex-wrap: wrap;
  }
}

高级布局技巧

1. 使用 Container Queries

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.card-container {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: 1rem;
  }
}

2. Subgrid 子网格

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.parent-grid {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 20px;
}

.child-grid {
  display: grid;
  grid-template-columns: subgrid;
  /* 继承父网格的列定义 */
}

3. 动态网格布局

1
2
3
4
5
6
7
8
9
.dynamic-grid {
  display: grid;
  gap: 20px;
  /* 根据容器宽度自动调整列数 */
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, 300px), 1fr)
  );
}

4. 层叠布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
.stack-layout {
  display: grid;
  /* 创建多个层 */
  grid-template-areas:
    "layer1"
    "layer2"
    "layer3";
}

.layer1 { grid-area: layer1; }
.layer2 { grid-area: layer2; }
.layer3 { grid-area: layer3; }

/* 使用 z-index 控制层叠顺序 */
.layer3 { z-index: 3; }
.layer2 { z-index: 2; }
.layer1 { z-index: 1; }

性能优化建议

1. 避免过度使用 Grid

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/* ✅ 简单布局使用 Flexbox */
.simple-flex {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ❌ 不必要的复杂 Grid */
.unnecessary-grid {
  display: grid;
  grid-template-columns: auto 1fr;
}

2. 合理使用 gap 属性

1
2
3
4
5
6
7
8
/* ✅ 使用 gap 代替 margin */
.grid-item {
  /* 不需要 margin */
}

.grid-container {
  gap: 20px; /* 统一间距 */
}

3. 优化重绘和重排

1
2
3
4
5
6
.optimized-grid {
  display: grid;
  /* 使用 transform 代替 top/left */
  transform: translateX(100px);
  will-change: transform; /* 提示浏览器优化 */
}

常见问题与解决方案

问题 1:内容溢出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.grid {
  display: grid;
  grid-template-columns: 300px 1fr;
  min-width: 0; /* 防止网格项溢出 */
}

.grid-item {
  min-width: 0;
  overflow: auto;
}

问题 2:等高布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/* Flexbox 方案 */
.flex-equal-height {
  display: flex;
  gap: 20px;
}

.flex-item {
  flex: 1;
}

/* Grid 方案 */
.grid-equal-height {
  display: grid;
  grid-auto-rows: 1fr; /* 自动等高 */
  gap: 20px;
}

问题 3:响应式图片

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
}

.image-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

总结

现代CSS布局技术让我们能够用更简洁、更语义化的方式创建复杂布局:

Flexbox 适合的场景:

  • 一维布局(行或列)
  • 组件内部布局
  • 垂直居中
  • 等间距分布

Grid 适合的场景:

  • 二维布局(行和列)
  • 页面整体布局
  • 复杂的对齐需求
  • 响应式网格系统

最佳实践:

  1. 先考虑整体布局是否需要Grid
  2. 组件内部优先使用Flexbox
  3. 善用auto-fill和auto-fit创建响应式布局
  4. 使用gap属性管理间距
  5. 合理结合两种布局技术

掌握这些现代布局技术,将大大提升你的CSS开发效率,让你能够轻松应对各种复杂的布局需求。


相关资源: