响应式布局怎么做?px、em、rem、vw 怎么选?

进阶高频实践约 5 分钟读完

一句话回答

响应式布局靠三样东西:相对单位让尺寸跟着参照物变化,媒体查询在断点处调整布局,弹性布局(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 方案

两种方案的目标一样:按设计稿等比缩放页面。

  1. rem 方案:用 JS 按屏幕宽度设置 html 的 font-size(例如屏宽的 1/10),所有尺寸写成 rem。早期的 lib-flexible 就是这个思路,配合 postcss-pxtorem 把设计稿的 px 自动转成 rem
  2. 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 挑合适尺寸的图片。

代码示例

CSS
/* 移动优先:先写小屏 */
.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 轮

登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录

这道题你掌握了吗?

选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。

学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。