CSS单位详解:px、em、rem、vw、vh、vmin、vmax的区别与适用场景
做前端这么多年,我见过太多同学在CSS单位上栽跟头。尤其是做大屏可视化,单位选不对,适配全白费。今天咱们就把这几个单位彻底聊透。
一、绝对单位:px
px(像素)是CSS里最基础的单位。一个px对应屏幕上的一个物理像素点。说白了,它就是最「实在」的单位——你说多大,它就多大。
适用场景:
- 边框宽度(border)
- 阴影大小(box-shadow)
- 1px的细线
- 固定尺寸的图标
注意:px不会随屏幕尺寸变化。在大屏适配中,千万别用px来定义布局尺寸。我曾经有个项目,所有字体都用px写死,结果在4K屏上字小得跟蚂蚁似的……嗯,后来全改了。
二、相对单位:em 与 rem
这两个单位都跟「字体大小」有关,但参照物不同。我刚开始也经常搞混,后来总结了一句话:em看父级,rem看根节点。
em
1em等于当前元素的font-size。如果当前元素没设font-size,就继承父级的。
/* 父级 */
.parent {
font-size: 16px;
}
/* 子元素 */
.child {
font-size: 1.5em; /* 实际 = 16px * 1.5 = 24px */
padding: 1em; /* 实际 = 24px * 1 = 24px(注意!参照的是自身的font-size) */
}
我的经验:em有个坑——它会「叠加」。嵌套多了,你根本算不清最终值是多少。我建议只在按钮、卡片这类独立组件里用em,别用在全局布局上。
rem
rem只参照根元素(<html>)的font-size。浏览器默认是16px,所以1rem = 16px。
/* 设置根字体大小 */
html {
font-size: 16px;
}
/* 所有rem都参照这个值 */
.title {
font-size: 2rem; /* 32px */
}
.content {
font-size: 1rem; /* 16px */
margin: 0.5rem; /* 8px */
}
适用场景:
- em:组件内部的间距、字体大小(比如按钮里的文字和padding)
- rem:全局统一的间距、字体层级、布局尺寸
为什么我推荐rem做大屏适配?因为你可以通过媒体查询或JS动态修改html的font-size,所有用rem的地方都会跟着变。这就是「弹性布局」的核心思路。
三、视口单位:vw、vh、vmin、vmax
这几个单位直接跟浏览器窗口大小挂钩。我做大屏可视化最常用的就是它们。
| 单位 | 含义 | 计算公式 |
|---|---|---|
| vw | 视口宽度的1% | 1vw = 视口宽度 / 100 |
| vh | 视口高度的1% | 1vh = 视口高度 / 100 |
| vmin | 取vw和vh中较小的那个 | vmin = min(vw, vh) |
| vmax | 取vw和vh中较大的那个 | vmax = max(vw, vh) |
vw 和 vh
这两个最常用。比如你想让一个元素占满整个屏幕:
.full-screen {
width: 100vw;
height: 100vh;
}
做大屏时,我经常用vw来定义字体大小:
/* 字体随屏幕宽度等比缩放 */
.title {
font-size: 3vw; /* 1920px宽时 = 57.6px,3840px宽时 = 115.2px */
}
曾经踩过的坑:移动端用100vh会有问题。因为手机浏览器的地址栏会占用空间,100vh实际会超出可视区域。我一般用100dvh(动态视口高度)或者配合JS来修正。
vmin 和 vmax
这两个单位比较「聪明」。它们会自动选择视口宽高中较小或较大的那个。
/* 保证元素在任何屏幕上都完整可见 */
.safe-area {
width: 50vmin; /* 取宽高中较小的50% */
height: 50vmin; /* 保证宽高相等,是个正方形 */
}
/* 全屏背景图 */
.background {
width: 100vmax; /* 取宽高中较大的100% */
height: 100vmax; /* 保证覆盖整个屏幕 */
}
我的习惯:做响应式大屏时,我会用vmin来设置最小字号。这样不管用户怎么缩放窗口,文字都不会小到看不清。你想想看,如果只用了vw,用户把窗口拉得很窄,字就缩没了——vmin能兜底。
四、实战对比:大屏适配怎么选?
咱们直接看一个实际的大屏项目配置:
/* 基础设置 */
html {
font-size: calc(100vw / 19.2); /* 以1920px设计稿为基准 */
}
/* 布局容器 */
.dashboard {
width: 100vw;
height: 100vh;
overflow: hidden;
}
/* 标题区域 */
.header-title {
font-size: 2rem; /* 相对根字体,随屏幕缩放 */
letter-spacing: 0.2em; /* 组件内部用em,保持比例 */
}
/* 数据卡片 */
.card {
width: 18vw; /* 按视口宽度分配 */
height: 22vh; /* 按视口高度分配 */
padding: 1.5rem; /* 统一间距 */
border: 1px solid #ccc; /* 边框用px,不变形 */
}
/* 图表容器 */
.chart-wrapper {
width: 80vmin; /* 保证在窄屏下也能完整显示 */
height: 60vmin;
}
总结一下我的选择原则:
- px:只用于边框、阴影、1px细线等「不能变」的东西
- em:组件内部的比例关系(按钮、卡片)
- rem:全局统一的尺寸和间距(配合JS动态修改根字体)
- vw/vh:按视口比例分配宽高、字体大小
- vmin/vmax:兜底方案,保证极端情况下的可用性
说实话,没有哪个单位是「万能药」。我一般会混合使用——rem做骨架,vw做缩放,px做细节,em做组件内部。这样既灵活又可控。
一个小技巧:如果你用vw设置字体,记得加个min()或clamp()限制范围。比如font-size: clamp(14px, 2vw, 48px),这样字不会太小也不会太大。我在好几个大屏项目里都这么用,效果很稳。
好了,CSS单位这块儿就聊到这儿。下节课咱们讲「大屏适配的核心策略——rem + vw 混合方案」,到时候会结合真实项目代码,一步步带你搭一套完整的适配体系。