请谈谈 em、px、rem、vh、vw 的区别,如何使用?
一、核心单位特性对比
单位 | 基准对象 | 计算特点 | 典型应用场景 | 坑点预警 |
---|---|---|---|---|
px | 设备像素 | 绝对单位,1px=1物理像素 | 边框、固定尺寸元素 | Retina屏显示过粗 |
em | 当前元素字体大小 | 多重继承,计算复杂度高 | 行高、相对字体间距 | 嵌套导致尺寸失控 |
rem | 根元素字体大小 | 单点控制,计算链路清晰 | 全局布局、响应式组件 | 未重置根字体导致意外缩放 |
vw | 视口宽度 | 1vw=1%视口宽 | 全屏布局、视口比例元素 | 移动端浏览器兼容差异 |
vh | 视口高度 | 1vh=1%视口高 | 高度自适应区块 | 移动端地址栏影响计算 |
二、深度使用指南
1. px:精确控制的利刃
/* 固定尺寸元素 */
.icon {
width: 24px; /* 始终显示为24物理像素 */
height: 24px; /* 适合需要像素级对齐的场景 */
}
/* Retina屏适配方案 */
@media (-webkit-min-device-pixel-ratio: 2) {
.border {
border: 0.5px solid #ccc; /* 使用0.5px实现真正细边框 */
}
}
注意:Safari等浏览器可能不支持0.5px,需配合transform实现
2. em:上下文敏感的弹簧
/* 嵌套字体系统 */
.card {
font-size: 16px;
padding: 1em; /* 16px */
}
.card-title {
font-size: 1.2em; /* 19.2px */
margin-bottom: 0.5em; /* 9.6px */
}
典型翻车现场:三层嵌套后尺寸指数级增长
3. rem:全局掌控的艺术
<!-- 基础设置 -->
<html style="font-size: 62.5%;"> <!-- 1rem = 10px -->
<body>
<div class="container" style="width: 32rem;"> <!-- 320px -->
</body>
/* 响应式调整 */
@media (max-width: 768px) {
html {
font-size: 50%; /* 1rem = 8px */
}
}
最佳实践:配合Sass函数提升可维护性
@function rem($px) {
@return ($px / 16) * 1rem;
}
.box {
width: rem(320); // 自动转换为20rem
}
4. vw/vh:视口舞者
/* 全屏布局方案 */
.hero-section {
width: 100vw;
height: 100vh; /* 小心移动端地址栏问题 */
padding: 5vw; /* 视口比例留白 */
}
/* 流体字号 */
.title {
font-size: clamp(2rem, 4vw, 3rem); /* 动态范围限制 */
}
移动端救星:修复100vh问题
.full-height {
height: 100vh;
height: -webkit-fill-available; /* 兼容Safari */
}
三、单位组合技
1. 响应式栅格系统
.grid-item {
width: calc(33.33% - 2rem);
margin: 1rem;
@media (max-width: 480px) {
width: calc(50vw - 3rem); /* 移动端适配 */
}
}
2. 动态间距系统
:root {
--space-unit: 1rem;
}
.spacing-xs {
margin: calc(var(--space-unit) * 0.5); /* 8px */
}
.spacing-xl {
margin: calc(var(--space-unit) * 2 + 1vw); /* 动态扩展 */
}
3. 视口比例容器
.aspect-box {
width: 50vw;
height: calc(50vw * 9/16); /* 16:9比例 */
position: relative;
}
四、避坑指南
1. em的继承陷阱
/* 错误示例 */
.parent {
font-size: 20px;
}
.child {
font-size: 0.8em; /* 16px */
padding: 2em; /* 32px! 而非预期的40px */
}
解决方案:改用rem或明确声明上下文
2. vh的移动端适配
// 动态修正vh值
function setRealVh() {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
window.addEventListener('resize', setRealVh);
.modal {
height: calc(var(--vh, 1vh) * 100);
}
3. rem基准重置风险
/* 危险操作 */
html {
font-size: 10px; /* 破坏浏览器默认缩放 */
}
/* 推荐方案 */
html {
font-size: 62.5%; /* 保持用户默认缩放 */
}
五、单位选择决策树
-
是否需要精确物理像素级控制?
- 是 → 使用px(边框、图标)
- 否 → 进入下一步
-
是否需要相对于父元素字体?
- 是 → 使用em(行高、文本相关间距)
- 否 → 进入下一步
-
是否需要全局比例控制?
- 是 → 使用rem(布局、组件尺寸)
- 否 → 进入下一步
-
是否需要视口比例响应?
- 是 → 使用vw/vh(全屏元素、流体字号)
- 否 → 考虑百分比或现代CSS单位(fr、min-content等)
六、未来趋势展望
-
容器查询单位(cqw/cqh)
.card { container-type: inline-size; } @container (width > 400px) { .title { font-size: max(2cqi, 1.5rem); } }
-
动态视口单位(dvh/dvw)
.mobile-tabbar { height: 100dvh; /* 自动排除地址栏高度 */ }
-
CSS数学函数
.responsive-text { font-size: min(max(1rem, 4vw), 2rem); }
总结建议
- 建立单位使用规范:团队约定基础单位(如rem为主,px为辅)
- 构建响应式基础:通过根字体+视口单位建立弹性系统
- 善用现代CSS特性:结合clamp()、min()、max()实现智能响应
- 移动端优先测试:重点验证vw/vh在不同设备的表现
- 性能与精度平衡:关键元素用px,普通布局用相对单位
通过理解各单位的底层逻辑,开发者可以像搭积木一样组合使用不同单位,在精确控制与弹性响应之间找到最佳平衡点。