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动态修改htmlfont-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 混合方案」,到时候会结合真实项目代码,一步步带你搭一套完整的适配体系。