第六章 · 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 + 媒体查询
桌面端用 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 节)?
- 横向滚动条是否只出现在刻意设计的容器(如代码块、表格)内,而不是意外出现在整个页面?