CSS Handbook · 布局

第六章 / 6.6 响应式布局实战

第六章 · 6.6 节

响应式布局实战


本节把前面四节的知识——盒模型、Flexbox、Grid、媒体查询——组合成一个真实可用的页面骨架:从流式字号、自适应卡片网格,到小屏下的导航折叠,逐步搭建一个能在手机到桌面显示器之间平滑过渡的页面。

流式字号:clamp() 三值函数

clamp(最小值, 首选值, 最大值) 让字号、间距可以随视口宽度连续变化,替代"在断点处生硬跳变"的做法。首选值通常写成 vw 单位,使其随视口线性缩放,同时用最小/最大值兜底,避免在极端尺寸下失控。

h1 {
  font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem);
}
.container {
  padding-inline: clamp(16px, 5vw, 64px);
}
为什么优于媒体查询媒体查询下字号在断点处会有肉眼可见的"跳变";clamp() 让变化连续平滑,且只需一行代码替代原本三四条媒体查询规则。

页面骨架:Grid 搭架子

先用 Grid 定义整站通用的页面级骨架——侧边栏、头部、主内容、页脚,移动端再用媒体查询把侧边栏"折叠"进主列:

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

@media (max-width: 768px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main";
  }
  .sidebar { display: none; } /* 交由折叠菜单代替 */
}

卡片列表:auto-fit 自适应

回顾 4.3 节的 auto-fit + minmax() 组合——它本身就是响应式的,甚至不需要额外写媒体查询就能应对绝大多数宽度变化:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(12px, 2vw, 24px);
}
效果预览:缩小浏览器窗口观察列数变化(此演示区域较窄,已呈现单列/双列状态)
卡片 A
卡片 B
卡片 C

桌面端用 Flexbox 横向平铺导航项,移动端切换为纵向折叠菜单——排布方式的切换只需要修改 flex-direction 一个属性:

.nav-list {
  display: flex;
  gap: 24px;
}

@media (max-width: 640px) {
  .nav-list {
    flex-direction: column;
    gap: 0;
    display: none; /* 默认收起,由汉堡按钮控制展开 */
  }
  .nav-list.open { display: flex; }
}

完整示例整合

把以上几段代码组合起来,就是一个具备基本响应能力的页面骨架雏形:流式字号负责文字层面的连续缩放,Grid 负责页面级骨架的断点重排,auto-fit 网格负责内容区卡片的自适应列数,Flexbox 负责导航栏这类一维组件在断点前后的方向切换。四者分工明确,各自解决自己最擅长的那一层问题,这正是现代响应式设计的核心思路——不是"一个大而全的方案",而是"在合适的层级选用合适的工具"。

上线前自查清单

  • 是否在 <head> 中声明了 <meta name="viewport" content="width=device-width, initial-scale=1">?缺少它,移动端媒体查询将完全失效。
  • 断点是否由内容决定,而非照搬某个设备型号的分辨率?
  • 触屏设备上的可点击区域是否足够大(建议不小于 44×44px)?
  • 是否用 prefers-reduced-motion 尊重了用户的动效偏好(见 3.2 节)?
  • 深色模式下的对比度、图片是否也经过检查(见 3.2 节)?
  • 横向滚动条是否只出现在刻意设计的容器(如代码块、表格)内,而不是意外出现在整个页面?