Develop

CSS 现代布局完全指南:Grid、Flexbox 与 Container Queries 实战

✎ -- 字 🕐 -- 分钟
字号
现代 CSS 布局决策树需要布局?是一维还是二维?一维 → Flexbox导航栏/卡片列表/居中二维 → Grid页面布局/仪表盘/画廊

前言

2025 年了,还在用 floatposition: absolute 做布局?本文覆盖 Flexbox、Grid 和 Container Queries 三大现代布局方案,从基础到进阶,30 分钟掌握 CSS 布局的全貌。

一、Flexbox:一维弹性的王者

1.1 核心属性速查

/* 容器属性 */
.container {
  display: flex;
  flex-direction: row | column;           /* 主轴方向 */
  justify-content: flex-start | center | space-between | space-around;
  align-items: stretch | center | flex-start | flex-end;
  flex-wrap: nowrap | wrap;               /* 换行 */
  gap: 16px;                              /* 间距(推荐替代 margin)*/
}

/* 子项属性 */
.item {
  flex: 1;              /* flex-grow | flex-shrink | flex-basis 简写 */
  align-self: center;   /* 单独覆盖 align-items */
  order: 1;             /* 排序(越小越靠前)*/
}

1.2 经典布局:圣杯导航栏

<nav class="navbar">
  <div class="nav-left">
    <img src="logo.svg" alt="Logo" />
  </div>
  <div class="nav-center">
    <a href="#">首页</a>
    <a href="#">博客</a>
    <a href="#">关于</a>
  </div>
  <div class="nav-right">
    <button>登录</button>
  </div>
</nav>
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
}
/* 自动左右撑开,中间居中 */
/* nav-left 靠左,nav-center 居中,nav-right 靠右 */

1.3 高级技巧:响应式卡片网格(无需 Grid)

.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.card {
  flex: 1 1 300px; /* grow shrink basis */
  /* 自动适配:最小 300px,空间够就平铺,不够就换行 */
  min-width: 0;     /* 防止内容溢出 */
}

二、CSS Grid:二维布局的终极方案

2.1 核心概念

.grid-container {
  display: grid;
  /* 三列:200px | 自适应填满 | 200px */
  grid-template-columns: 200px 1fr 200px;
  /* 行高:首行 auto 高度,其余最小 100px */
  grid-template-rows: auto;
  grid-auto-rows: minmax(100px, auto);
  gap: 16px;
}

2.2 实战:仪表盘布局

.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: auto;
  gap: 16px;
  grid-template-areas:
    "stats   stats   stats   sidebar"
    "chart1  chart1  chart2  sidebar"
    "table   table   table   sidebar";
}

.stats   { grid-area: stats; }
.chart-1 { grid-area: chart1; }
.chart-2 { grid-area: chart2; }
.table   { grid-area: table; }
.sidebar { grid-area: sidebar; }

/* 响应式:小屏变单列 */
@media (max-width: 768px) {
  .dashboard {
    grid-template-columns: 1fr;
    grid-template-areas:
      "stats"
      "chart1"
      "chart2"
      "table"
      "sidebar";
  }
}

2.3 Grid 实用技巧:自适应列数

/* 无需媒体查询,自动根据容器宽度增减列数 */
.grid-auto {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}
/* auto-fill: 尽可能多放 → 适合卡片列表 */
/* auto-fit: 拉伸填满 → 适合居中少量元素 */

/* 进阶:列数范围控制 */
.grid-bounded {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr));
  gap: 16px;
}

三、Container Queries:组件级响应式的未来

传统 @media 查询只能基于视口宽度响应。Container Queries 让你基于父容器宽度响应——真正的组件级响应式。

/* 1. 定义容器 */
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

/* 2. 基于容器宽度响应 */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 150px 1fr;
    gap: 16px;
  }
  .card-image { border-radius: 12px 0 0 12px; }
}

@container card (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: column;
  }
  .card-image { border-radius: 12px 12px 0 0; }
}
<!-- 无论放在哪里,卡片根据自身容器自适应 -->
<div class="sidebar"> <!-- 300px 宽 → 卡片竖排 -->
  <div class="card-wrapper">
    <div class="card">...</div>
  </div>
</div>

<div class="main"> <!-- 700px 宽 → 卡片横排 -->
  <div class="card-wrapper">
    <div class="card">...</div>
  </div>
</div>

四、Flexbox vs Grid 选型指南

场景推荐理由
导航栏 / 工具栏Flexbox一维排列,内容驱动宽度
整体页面布局Grid行+列同时控制,grid-template-areas 语义化
卡片列表都可以内容不自知宽度 → Flex;需要严格行列对齐 → Grid
仪表盘 / 后台Grid二维精确控制,命名区域
居中单个元素Flexbox3 行代码: display:flex; align-items:center; justify-content:center
响应式组件Container Queries基于容器而非视口,真正的组件化

五、浏览器兼容性

特性ChromeSafariFirefox
Flexbox29+9+28+
Grid (基础)57+10.1+52+
Subgrid117+16+71+
Container Queries105+16+110+
gap in Flexbox84+14.1+63+

学习建议:先用 Flexbox 解决 80% 的布局问题,Grid 处理复杂页面结构,Container Queries 让组件真正独立。三者各司其职,不必非此即彼。Grid 也可以嵌套 Flexbox,反之亦然。