前端基础丨CSS 尺寸单位:px、em、rem、vw 的区别和用法

www.jswusn.com CSS 2026-06-06 09:54:01 6次浏览


写微信小程序的时候,有一个单位叫 rpx。规则非常简单:不管手机屏幕多宽,整个屏幕宽度始终等于 750rpx。设计稿按 750 画,元素宽度是 375rpx,就是半个屏幕。大屏上半个屏幕,小屏上还是半个屏幕,换算全由框架处理。

Web 里没有这种"生来响应式"的单位,而AI 写 Web 样式时,默认用 px——数字直观,写出来就是那么多像素。但 px 是固定的,不随屏幕变化。桌面上 16px 的字看着正常,手机屏幕一换,该缩的不缩,该放的不放,布局就乱了。

em、rem、vw 这套组合,每一个解决的是不同场景下的响应式问题,不是同一件事的四种写法。

未标题-1.jpg

px 固定 vs rem/vw 响应式尺寸对比

px:不跟任何东西走的固定值

.card {
  width: 320px;
  font-size: 16px;
  border: 1px solid #e0e0e0;
}

px 是最直接的单位——写 320px 就是 320 个 CSS 像素,跟屏幕宽度无关,跟父元素无关,跟字号设置无关。

这不是坏事。很多东西就该固定:边框厚度(1px)、圆角(4px)、分割线(1px)、图标尺寸(24px)——这些值在大屏和小屏上都应该保持一致,用 px 反而是对的。

不适合用 px 的,是那些需要随屏幕或字号变化的东西:整体布局宽度、段落字号、内外边距。用了 px,就等于把适配工作全部扔给 media query 手动处理,维护成本很高。

AI 写布局容器、字号、间距时倾向于用 px,这是最常见的翻车点。想改掉这个习惯,一条指令就够:

字号和间距用 rem,响应式容器宽度用 vw 或百分比,固定装饰类尺寸(border、border-radius、icon 大小)用 px。


em:跟父元素字号走,嵌套会叠加

.parent {
  font-size: 16px;
}

.child {
  font-size: 1.5em;   /* 16 × 1.5 = 24px */
  padding: 1em;       /* 24 × 1 = 24px */
}


em 是相对值——1em 等于当前元素的字号。当前元素没有显式设字号,就往父元素找,一层一层往上,直到找到为止。

padding、margin 用 em 时,计算基准是当前元素自己的字号,不是父元素的。padding: 1em 的意思是:内边距等于这个元素的字号大小。这没什么问题——按钮的内边距跟着按钮字号走,字号变了内边距也跟着变,天然自适应。

问题出在嵌套。

.outer {
  font-size: 1.2em;  /* 假设继承了 16px:16 × 1.2 = 19.2px */
}
.inner {
  font-size: 1.2em;  /* 19.2 × 1.2 = 23.04px */
}
.innermost {
  font-size: 1.2em;  /* 23.04 × 1.2 = 27.65px */
}

每嵌套一层,字号就乘一次。嵌深了,字号会越滚越大,和写的时候想的完全不一样。

未标题-2.jpg

em 嵌套叠加 vs rem 稳定的对比示意

em 最适合的场景是组件内部、跟字号强相关的间距——比如按钮的左右 padding 用 em,字号调大了,按钮的留白自动跟着变宽,视觉比例不变。全局字号不适合用 em,那是 rem 的活。


rem:跟 html 根字号走,改一处全改

html {
  font-size: 16px;  /* 根字号 */
}

h2 {
  font-size: 1.5rem;  /* 16 × 1.5 = 24px */
}

p {
  font-size: 1rem;    /* 16 × 1 = 16px */
  margin-bottom: 1.5rem;  /* 16 × 1.5 = 24px */
}


rem 全称 root em,计算基准永远是 html 元素的字号。不管嵌套多深,1rem 始终等于 html 的字号——不叠加,不漂移。

rem 的价值就在这里——整站所有用了 rem 的尺寸,只需要改一个地方:html { font-size },全部联动。浏览器默认 html 字号是 16px,如果把浏览器字号调大,基于 rem 的布局会自动跟着放大,无障碍体验更好。

未标题-3.jpg

rem 工作原理:所有尺寸指向根字号

再进一步,可以在响应式里直接调根字号:

html {
  font-size: 14px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

小屏整体缩小,大屏恢复正常。改的只是一行,不用逐条 media query 覆盖每个元素。

字号和间距,默认推荐 rem。给 AI 的指令:

字号统一用 rem,根字号设 16px。间距(padding、margin)优先用 rem,只有 border 和 box-shadow 等装饰性尺寸保留 px。


vw / vh:直接跟视口走

.hero {
  width: 100vw;    /* 视口宽度的 100% */
  height: 60vh;   /* 视口高度的 60% */
}

.section-title {
  font-size: 5vw;  /* 视口宽度的 5% */
}


1vw 等于视口宽度的 1%,1vh 等于视口高度的 1%。视口是浏览器可见区域的大小,和父元素、根字号都无关。

未标题-4.jpg

vw/vh 视口宽高百分比示意

vw 最适合的场景:

  • 全宽容器:需要撑满整个屏幕宽度,width: 100vwwidth: 100% 更可靠,因为 100% 是相对父元素的
  • Hero 区域高度height: 60vh 让 Hero 始终占视口高度的六成,不管屏幕多高
  • 大字号标题:大屏上想要显眼的标题,font-size: 4vw 会随屏幕变宽自动放大

细小组件的内部尺寸不适合用 vw——按钮 padding、卡片 margin 用了 vw,宽屏上会过度放大,用 rem 更合适。

clamp() 是更现代的写法,设定最小值、首选值和最大值,字号在范围内线性响应:

h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
  /* 最小 24px,随 vw 变化,最大 48px */
}


不用写 media query,字号还能平滑过渡,在响应式场景里越来越常用。给 AI 的指令:

Hero 区域和全屏容器用 vw/vh,响应式标题可以用 clamp(最小值, vw, 最大值),组件内间距用 rem。



小程序 rpx 对比看一下

回到最开始说的 rpx。小程序的逻辑是:屏幕宽度 = 750rpx,设计稿也按 750 画,元素宽 375rpx 就是半屏,简单直接。

Web 为什么没有这种单位?两个原因。

第一,历史债。Web 比小程序早了二十年,最早的 CSS 里只有 px,响应式概念是后来才慢慢加进来的,em、rem、vw 是一步一步打补丁打出来的体系,不是一开始就设计好的。

第二,多端复杂性。Web 要处理的屏幕差异远比小程序大——从 320px 的旧手机到 4K 显示器,字号缩放、系统设置、浏览器偏好都要兼顾。rpx 的简洁是以锁定特定设备假设为代价的,Web 没有这个条件。

在 Web 里最接近 rpx 的做法,是把根字号设成 vw,全站再用 rem:

html {
  font-size: calc(100vw / 37.5);  /* 以 375 宽为基准,1rem ≈ 10px */
}


这样 rem 就有了"跟屏幕宽成比例"的特性,用起来和 rpx 差不多是一回事。


各单位适用场景速查

未标题-5.jpg

CSS 单位使用场景速查表


技术分享

苏南名片

  • 联系人:吴经理
  • 电话:152-1887-1916
  • 邮箱:message@jswusn.com
  • 地址:江苏省苏州市相城区

热门文章

Copyright © 2018-2026 jswusn.com 版权所有

技术支持:苏州网站建设  苏ICP备18036849号