前言
CSS 中有多种长度单位,每个单位都有其特定的适用场景。正确选择单位不仅能让代码更简洁,还能实现更灵活、更响应式的布局。本文深入解析 px、em、rem、vw、vh、clamp 六种最常用的 CSS 单位。
一、px(像素)
1.1 什么是 px
px 是 CSS 中最常用的绝对长度单位,代表屏幕上的一个物理像素点。
1.2 特点
- 绝对单位:固定值,不受其他元素影响
- 屏幕像素:1px 通常对应屏幕上的一个物理像素点
- 不会继承:不受父元素字体大小影响
- 精确控制:适合需要精确尺寸的场景
1.3 使用场景
css
/* 边框、阴影等精确值 */
.box {
border: 1px solid #ccc;
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}
/* 图标、头像等固定尺寸 */
.avatar {
width: 48px;
height: 48px;
}
/* 最小尺寸限制 */
.min-size {
min-width: 100px;
min-height: 100px;
}
1.4 缺点
- 不支持响应式,屏幕尺寸变化时需要手动修改
- 在高 DPI 屏幕上,1px 可能显示为多个物理像素
二、em
2.1 什么是 em
em 是相对长度单位,相对于当前元素或其父元素的字体大小计算。
2.2 特点
- 相对单位:相对于父元素或当前元素的 font-size
- 继承性:会继承父元素的字体大小
- 级联效应:嵌套元素会层层相乘
2.3 计算规则
css
/* 父元素 font-size 为 16px */
.parent {
font-size: 16px;
}
/* 子元素 1em = 16px,所以 2em = 32px */
.child {
font-size: 2em; /* 32px */
/* 内边距 1em = 32px */
padding: 1em;
}
2.4 级联问题演示
html
<div style="font-size: 16px">
<div style="font-size: 2em"> <!-- 32px -->
<div style="font-size: 2em"> <!-- 64px,级联相乘 -->
这段文字会非常大!
</div>
</div>
</div>
2.5 使用场景
- 需要随字体大小缩放的元素
- 组件内部的比例布局
css
.button {
font-size: 16px;
padding: 0.5em 1em; /* 相对于字体大小,8px 16px */
border-radius: 0.25em; /* 4px */
}
三、rem(Root em)
3.1 什么是 rem
rem 是相对长度单位,相对于**根元素(html)**的字体大小计算。
3.2 特点
- 相对根元素:始终相对于 html 元素的 font-size
- 无级联问题:不会像 em 那样层层相乘
- 全局一致:所有元素使用同一基准
3.3 与 em 的对比
css
html {
font-size: 16px;
}
.parent {
font-size: 20px; /* 忽略 */
}
.child-em {
font-size: 2em; /* 40px(相对于父元素) */
}
.child-rem {
font-size: 2rem; /* 32px(始终相对于根元素) */
}
3.4 使用场景
css
/* 响应式字体大小 */
html {
font-size: 16px;
}
h1 {
font-size: 2rem; /* 32px */
}
h2 {
font-size: 1.5rem; /* 24px */
}
p {
font-size: 1rem; /* 16px */
}
/* 组件化开发 */
.card {
padding: 1rem;
margin-bottom: 1rem;
}
3.5 响应式 rem 技巧
css
/* 基于视口大小调整根字体 */
html {
font-size: calc(12px + 0.5vw);
}
h1 {
font-size: 2rem; /* 自动响应式 */
}
四、vw(Viewport Width)
4.1 什么是 vw
vw 是相对长度单位,1vw = 视口宽度的 1%。
4.2 特点
- 视口相对:相对于浏览器窗口宽度
- 响应式友好:自动响应窗口大小变化
- 全屏布局:非常适合全屏或大面积布局
4.3 计算示例
css
/* 视口宽度为 1200px 时 */
.box {
width: 50vw; /* 600px */
}
/* 100vw = 整个视口宽度 */
.full-width {
width: 100vw;
}
4.4 使用场景
css
/* 全屏 Hero 区域 */
.hero {
height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
}
/* 响应式字体 */
.responsive-text {
font-size: 4vw; /* 随视口缩放 */
}
/* 响应式留白 */
.container {
padding: 5vw;
}
4.5 注意事项
vw 包括滚动条宽度,可能导致水平滚动条。使用 100% 代替 100vw 可以避免这个问题。
css
/* 避免滚动条问题 */
.full-screen {
width: 100%; /* 推荐 */
/* width: 100vw; 可能包含滚动条 */
}
五、vh(Viewport Height)
5.1 什么是 vh
vh 是相对长度单位,1vh = 视口高度的 1%。
5.2 特点
- 视口相对:相对于浏览器窗口高度
- 移动端友好:适合移动端全屏布局
- 高度控制:完美实现视口高度适配
5.3 使用场景
css
/* 全屏页面 */
.landing-page {
height: 100vh;
}
/* 固定顶部 + 滚动内容 */
.layout {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
height: 60px;
}
.content {
flex: 1;
overflow-y: auto;
}
/* 居中弹窗 */
.modal-overlay {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.5);
}
.modal {
width: 90vw;
max-width: 500px;
height: 70vh;
}
5.4 移动端视口问题
移动端浏览器的地址栏会动态显示/隐藏,导致 100vh 可能超出可视区域。
css
/* 解决方案:使用 min-height */
.full-section {
min-height: 100vh;
/* 或使用 env() 获取安全区域 */
padding-bottom: env(safe-area-inset-bottom);
}
六、clamp()
6.1 什么是 clamp()
clamp() 是一个 CSS 函数,返回一个值被限制在指定范围内。语法:
css
clamp(min, preferred, max)
- min:最小值(下限)
- preferred:首选值(可以是表达式)
- max:最大值(上限)
6.2 语法解析
css
font-size: clamp(16px, 4vw, 32px);
这段代码表示:
- 最小值:16px
- 首选值:视口的 4%
- 最大值:32px
实际效果:字体会在 16px 到 32px 之间随视口变化,超出范围则使用边界值。
6.3 使用场景
css
/* 响应式字体 */
.responsive-heading {
font-size: clamp(1.5rem, 4vw, 3rem);
}
/* 流体间距 */
.section {
padding: clamp(1rem, 5vw, 3rem);
}
/* 流体宽度 */
.card {
width: clamp(300px, 80vw, 600px);
}
/* 响应式布局 */
.container {
width: clamp(320px, 90vw, 1200px);
margin: 0 auto;
}
6.4 clamp 替代方案
在没有 clamp 之前,实现类似效果需要复杂写法:
css
/* 之前的方式:使用媒体查询 */
.text {
font-size: 16px;
}
@media (min-width: 480px) {
.text {
font-size: 20px;
}
}
@media (min-width: 768px) {
.text {
font-size: 24px;
}
}
@media (min-width: 1200px) {
.text {
font-size: 32px;
}
}
/* 现在:一行搞定 */
.text {
font-size: clamp(16px, 2.5vw + 12px, 32px);
}
6.5 clamp 表达式计算
css
/* clamp() 中可以使用数学表达式 */
.box {
/* 最小 200px,首选 (50vw + 100px),最大 800px */
width: clamp(200px, 50vw + 100px, 800px);
}
/* 配合 calc 灵活计算 */
.responsive-card {
width: clamp(280px, calc(30vw + 50px), 400px);
padding: clamp(10px, 2vw, 24px);
}
七、单位对比总结
7.1 单位特性对比表
| 单位 | 类型 | 参照物 | 响应式 | 使用频率 |
|---|---|---|---|---|
| px | 绝对 | 无 | ❌ | ⭐⭐⭐⭐⭐ |
| em | 相对 | 父元素字体 | ⚠️ 需注意级联 | ⭐⭐⭐ |
| rem | 相对 | 根元素字体 | ✅ | ⭐⭐⭐⭐⭐ |
| vw | 相对 | 视口宽度 | ✅ | ⭐⭐⭐⭐ |
| vh | 相对 | 视口高度 | ✅ | ⭐⭐⭐⭐ |
| clamp | 函数 | 可混合 | ✅ | ⭐⭐⭐⭐ |
7.2 场景推荐
| 场景 | 推荐单位 |
|---|---|
| 边框、阴影 | px |
| 固定尺寸图标 | px |
| 组件内比例布局 | em / rem |
| 全屏布局 | vh / vw |
| 响应式字体 | clamp() / rem |
| 响应式间距 | clamp() / vw |
| 流体容器 | clamp() / % |
八、实战最佳实践
8.1 现代 CSS 单位使用策略
css
/* 根字体设置 */
html {
font-size: 16px;
}
/* 使用 rem 作为主要单位 */
.card {
padding: 1.5rem;
margin-bottom: 1rem;
border-radius: 0.5rem;
}
/* 使用 clamp 实现流体设计 */
.fluid-title {
font-size: clamp(1.5rem, 5vw, 3rem);
}
.fluid-spacing {
padding: clamp(1rem, 3vw, 2rem);
}
/* 使用 vh 实现全屏区块 */
.hero {
height: 100vh;
display: flex;
align-items: center;
}
/* 使用 vw 实现全宽布局 */
.banner {
width: 100vw;
margin-left: calc(50% - 50vw); /* 修正视口偏移 */
}
8.2 响应式排版公式
css
/* 推荐的响应式字体公式 */
:root {
--min-fz: 1rem; /* 最小字体 */
--max-fz: 2rem; /* 最大字体 */
--slope: 0.05vw; /* 变化斜率 */
}
h1 {
font-size: clamp(
var(--min-fz),
/* 计算值 = 最小值 + 斜率 × 视口宽度 */
calc(var(--min-fz) + var(--slope) * 100vw),
var(--max-fz)
);
}
8.3 移动端适配模板
css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
}
body {
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.5;
color: #333;
}
/* 移动优先的响应式容器 */
.container {
width: 100%;
padding: 1rem;
}
@media (min-width: 768px) {
.container {
width: 720px;
margin: 0 auto;
padding: 2rem;
}
}
@media (min-width: 1024px) {
.container {
width: 960px;
}
}
@media (min-width: 1280px) {
.container {
width: 1200px;
}
}
九、浏览器兼容性
9.1 支持情况
| 单位 | IE | Edge | Chrome | Firefox | Safari | iOS Safari |
|---|---|---|---|---|---|---|
| px | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| em | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| rem | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| vw | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| vh | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| clamp | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
9.2 兼容性处理
css
/* clamp 的降级处理 */
.responsive-text {
font-size: 16px; /* 旧浏览器回退值 */
font-size: clamp(16px, 4vw, 32px); /* 现代浏览器 */
}
十、总结
- px 是基础,适合边框、阴影、固定尺寸
- em 适合组件内部比例布局,但需注意级联
- rem 是最推荐的相对单位,适合全局一致的缩放
- vw/vh 适合全屏布局、视口相关设计
- clamp() 是最强武器,一行实现流体设计
现代 CSS 开发中,rem + vw/vh + clamp() 的组合能应对 95% 的场景,既保证了开发效率,又实现了优雅的响应式体验。