CSS 布局经历了从浮动(float)到定位(position),再到 Flexbox 和 Grid 的演进,如今容器查询(Container Queries)又带来了全新的响应式思路。这篇文章帮你梳理主流布局方案的适用场景,让你不再对着满屏的 margin: auto 发愁。
Flexbox 擅长处理一行或一列的排列问题,是目前使用最广泛的布局方式。
.container {
display: flex;
/* 主轴方向 */
flex-direction: row | column;
/* 主轴对齐 */
justify-content: flex-start | center | space-between | space-around;
/* 侧轴对齐 */
align-items: stretch | center | flex-start;
/* 换行控制 */
flex-wrap: nowrap | wrap;}
<nav class="navbar">
<div class="logo">Logo</div>
<ul class="nav-links">
<li>首页</li>
<li>产品</li>
<li>关于</li>
</ul>
<button class="login-btn">登录</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;}
什么时候用 Flexbox?
导航栏、按钮组、卡片内部排列
元素水平/垂直居中
子元素需要自适应伸缩
当布局需要同时控制行和列时,Grid 是更好的选择。
.container {
display: grid;
/* 定义列宽 */
grid-template-columns: repeat(3, 1fr);
/* 定义行高 */
grid-template-rows: auto;
/* 间距 */
gap: 16px;
/* 区域命名 */
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";}
.layout {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr 48px;
height: 100vh;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";}.header { grid-area: header; }.sidebar { grid-area: sidebar; }.main { grid-area: main; overflow-y: auto; }.footer { grid-area: footer; }
| 技巧 | 代码 | 说明 |
|---|
| 自适应列 | repeat(auto-fill, minmax(280px, 1fr)) | 自动填充,最小280px |
| 跨列/跨行 | grid-column: span 2 | 跨越多列 |
| 垂直对齐 | align-content | 整个网格在容器中对齐 |
CSS Grid Level 2 引入的 subgrid 是一个被严重低估的特性。
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;}.card {
/* 子元素对齐到父网格 */
display: grid;
grid-template-rows: subgrid;
row-gap: 16px;}.card h2 { /* 与其他卡片标题对齐 */ }.card p { /* 与其他卡片内容对齐 */ }
效果: 无论各卡片内容多少,标题始终在同一行,内容区域自动调整。
传统媒体查询基于视口(viewport),而容器查询让组件能够根据自身容器大小来调整样式——这才是真正的组件化响应式。
/* 定义容器 */.card-wrapper {
container-type: inline-size;
container-name: card;}/* 根据容器宽度查询 */@container card (min-width: 400px) {
.card {
flex-direction: row;
}}
<!-- 同一个卡片组件 --><div class="card-wrapper">
<div class="card">
<img src="thumb.jpg" />
<div class="card-content">
<h3>标题</h3>
<p>描述文字...</p>
</div>
</div></div>
/* 视口宽度 < 768px 时,整行变窄,图片被压缩 *//* 容器宽度 > 400px 时,卡片自动变成左右布局 *//* 两者互不干扰,组件可复用 */
适用场景:
卡片在不同页面有不同宽度
侧边栏折叠时组件自适应
文章详情页和列表页共用同一组件
/* 方法一:Flexbox */.parent {
display: flex;
justify-content: center;
align-items: center;}/* 方法二:Grid */.parent {
display: grid;
place-items: center;}/* 方法三:绝对定位 + transform */.parent {
position: relative;}.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);}
.header {
position: sticky;
top: 0; /* 滚动到顶部时固定 */
z-index: 100;}
.item {
flex-shrink: 0; /* 不允许收缩 */
flex-basis: 200px;}
h1 {
font-size: clamp(1.5rem, 5vw, 3rem);
/* 最小1.5rem,最大3rem,中间随视口宽度缩放 */}
| 场景 | 推荐方案 |
|---|
| 导航栏、按钮组 | Flexbox |
| 卡片网格、相册 | Grid |
| 表单排列 | Flexbox |
| 页面整体框架 | Grid |
| 组件响应式 | 容器查询 |
| 粘性头部/侧边栏 | position: sticky |
| 内容溢出处理 | Flexbox + flex-wrap |
CSS 布局没有"最优解",只有"最适合的解"。记住三个原则:
能用 Flexbox 解决的,不用 Grid——Flexbox 更轻量
需要行列同时控制时,用 Grid——Grid 更强大
组件需要自己的响应式时,用容器查询——真正的模块化
熟练掌握这三种方案,日常工作里 90% 的布局问题都能迎刃而解。