px rem em 单位换算

同一个长度换成 px、rem、em、vw、vh、pt,根字号和视口变了结果也跟着变。

绝对像素,不随字号和视口变化

单位依赖什么

px 是绝对单位,也是其他单位换算的中转站。rem 只依赖根元素字号:浏览器默认是 16px,所以 1rem = 16px、0.875rem = 14px。常见做法是把 html 的字号设成 62.5%,让 1rem = 10px,这样设计稿上的 14px 直接写 1.4rem,心算方便;代价是用户如果改了默认字号,比例会跟着变。

em 和 % 依赖父级字号,而且会嵌套累乘。父级设了 1.5em,子级再设 1.5em,实际是 2.25 倍,这就是「明明写了 1.5em 却大得离谱」的原因。% 在字号上是相对父级字号的百分比,100% 等于 1em,两者可以互相替换。做组件内部的自适应间距时用 em 很合适,做全局尺寸就不合适。

vw 和 vh 的陷阱

vw 是视口宽度的百分之一。视口宽度会随纵向滚动条出现而变小,桌面浏览器里 100vw 通常比实际可用宽度多出滚动条那十几像素,于是出现横向滚动。用 width: 100% 更稳。vh 在移动端的问题更明显:地址栏收起前后可视高度不同,100vh 是按较大的那个算的,底部内容可能被裁掉,现代浏览器提供了 dvh 来按动态视口计算。

可访问性与最小字号

字号建议用 rem 而不是 px,这样用户在浏览器里调大默认字号时页面会跟着放大。Chrome 对小于 12px 的中文有最小字号限制,设 10px 实际仍按 12px 渲染,这不是换算错了。pt 在 CSS 里固定等于 96/72px,和物理 DPI 无关,所以 12pt 永远是 16px。要处理设计稿里的颜色和间距,可以配合颜色转换和Flex 与 Grid 布局生成一起用。

常见问题

rem 和 em 到底差在哪?

rem 只认根元素(html)的字号,整页只有一个基准,所以用 rem 做间距和字号最稳定。em 认的是当前元素的父级字号,父级变了子级跟着变,嵌套几层就会累乘:父级 1.5em、子级又 1.5em,实际是 2.25 倍。适合需要「跟着上下文缩放」的场合,不适合做全局尺寸。

为什么 14px 转成 rem 是 0.875?

14 / 16 = 0.875,这是根字号为 16(浏览器默认)时唯一的结果。只有改过 html 的 font-size,比如移动端设成 62.5% 让 1rem = 10px,结果才会变。页面上可以把根字号改成 10 再算一遍,对照两种方案。

该用 px 还是 rem?

字号和依赖字号的比例用 rem(或 em),边框、阴影、1px 细线用 px。全用 px 的问题在于用户改了浏览器默认字号后页面不跟着放大,属于可访问性问题。另一个折中是 clamp() 配合 rem,让字号随视口平滑变化,但要注意设置上下限。

vw 和 vh 能放心用来做全屏布局吗?

要小心。100vh 在移动端浏览器里包含地址栏区域,地址栏收起时元素会被裁掉一截,所以现在更推荐 100dvh(动态视口高度)。vw 的问题是出现纵向滚动条时视口宽度会变小,100vw 可能比实际可用宽度多出十几像素,造成横向滚动。

为什么小于 12px 的字在页面上看起来比设定的大?

Chrome 和部分浏览器有最小字号限制,默认不会渲染小于 12px 的中文,设定 10px 实际仍按 12px 显示。这不是换算错误,而是浏览器行为。需要更小的字时,通常要靠缩放整个容器(transform: scale)而不是继续压字号。

pt 和 px 是固定比例吗?

在 CSS 里是:1pt 等于 96/72 px,也就是 1.3333px,和屏幕实际 DPI 无关。所以 12pt = 16px。打印样式里 pt 更常见,屏幕上一律按这个比例换算即可,不需要知道显示器是多少 DPI。