响应式布局怎么做?px、em、rem、vw 怎么选?
一句话回答
响应式布局靠三样东西:相对单位让尺寸跟着参照物变化,媒体查询在断点处调整布局,弹性布局(Flex、Grid)让内容自动排列。单位按参照物选:px 固定,em 相对当前元素字号,rem 相对根元素字号,vw/vh 相对视口。移动端整体缩放常用 rem 或 vw 方案,字号用 clamp() 做流式变化,全屏高度用 dvh 代替有问题的 100vh。
详细解析
各单位的参照物
| 单位 | 参照物 | 典型用途 |
|---|---|---|
px |
CSS 像素,不随其他元素变化 | 边框、阴影、细小间距 |
em |
当前元素的 font-size;用在 font-size 上时参照父元素字号 |
和字号成比例的内边距、图标尺寸 |
rem |
根元素 html 的 font-size |
全局字号、间距,整体缩放方案 |
% |
随属性变:width 参照包含块宽度,height 参照包含块高度 |
流式宽度 |
vw / vh |
视口宽度 / 高度的 1% | 整屏布局、移动端等比缩放 |
dvh / svh / lvh |
动态 / 最小 / 最大视口高度的 1% | 移动端全屏区域 |
em 会层层叠加:父元素 1.2em、子元素再 1.2em,子元素字号就是根字号的 1.44 倍。需要稳定的全局比例时用 rem。
移动端整体适配:rem 方案和 vw 方案
两种方案的目标一样:按设计稿等比缩放页面。
- rem 方案:用 JS 按屏幕宽度设置
html的font-size(例如屏宽的 1/10),所有尺寸写成rem。早期的 lib-flexible 就是这个思路,配合 postcss-pxtorem 把设计稿的px自动转成rem - vw 方案:直接用
vw表达比例。375 宽的设计稿上1px等于100 / 375 vw,用 postcss-px-to-viewport 这类插件自动换算,不需要 JS
现在更推荐 vw 方案:不依赖 JS,没有脚本执行前的样式跳动。两种方案都有一个共同问题:大屏上会无限放大,需要给容器加 max-width 或者配合媒体查询限制。
媒体查询与移动优先
移动优先:基础样式写给小屏,再用 min-width 逐级给大屏加样式。小屏设备不需要先套用桌面样式再逐条覆盖回来,代码量更少、也更好维护。注意不匹配的媒体查询里的样式照样会被下载和解析,移动优先省的是覆盖逻辑,不是下载量。断点按内容在哪里"挤不下"来定,不必对着某款设备的宽度。
流式字号与移动端视口高度
clamp(最小值, 首选值, 最大值) 让字号在两个边界之间随视口平滑变化,不用写一堆断点。首选值里最好带上 rem(如 1rem + 2vw):纯 vw 的字号不会响应用户的浏览器默认字号设置,桌面端放大页面时也几乎不变大,不利于需要大字的用户。
移动端浏览器的地址栏会伸缩,100vh 通常按地址栏收起时的最大高度计算,页面初始时底部会被遮住一截。新的视口单位把这几种情况分开:svh 是地址栏展开时的最小高度,lvh 是收起时的最大高度,dvh 随地址栏实时变化。
图片的响应式交给 srcset 和 sizes,让浏览器按屏幕宽度和 DPR 挑合适尺寸的图片。
代码示例
/* 移动优先:先写小屏 */
.list {
display: grid;
gap: 1rem;
}
@media (min-width: 768px) {
.list { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1200px) {
.list { grid-template-columns: repeat(3, 1fr); }
}
/* 流式标题:最小 1.5rem,最大 3rem,中间随视口变化 */
h1 {
font-size: clamp(1.5rem, 1rem + 2.5vw, 3rem);
}
/* 全屏首屏:不支持 dvh 的浏览器用上一行的 vh 兜底 */
.hero {
min-height: 100vh;
min-height: 100dvh;
}
面试官可能追问
为什么桌面端 width: 100vw 会出现横向滚动条?
vw 按整个视口宽度计算,包含了竖向滚动条的宽度。页面出现竖向滚动条时,100vw 比可用宽度多出一个滚动条的宽,就会撑出横向滚动条。需要占满宽度时用 width: 100%,或者从布局上避免依赖 100vw。
为什么有人把 html 的 font-size 设成 62.5%?
浏览器默认字号一般是 16px,62.5% 就是 10px,换算时 1.6rem 就是 16px,好算。和直接写 font-size: 10px 相比,百分比会跟着用户在浏览器里设置的默认字号缩放,对需要大字号的用户更友好。
媒体查询里的 width 是什么宽度?
是视口宽度,也就是布局视口的宽度,单位是 CSS 像素,不是设备的物理像素。所以必须先设置好 viewport meta,否则移动端的布局视口可能是 980px 左右的默认宽度,断点会全部失效,详见 移动端适配。
易错点
em用在font-size上参照父元素字号,用在其他属性上参照当前元素自己的字号padding、margin的百分比无论上下还是左右,都参照包含块的宽度height: 100%要生效,父元素必须有明确的高度- rem/vw 等比缩放适合移动端 H5,不适合内容型的桌面网站,后者更适合流式布局加断点
AI 模拟面试官
用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮
这道题你掌握了吗?
选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。
学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。