这三个是 CSS 中最常用的单位,理解它们的区别对于构建响应式、可访问的网站至关重要。
一、核心概念速览
| 特性 | px(像素) | em(相对父元素) | rem(相对根元素) |
|---|---|---|---|
| 参照基准 | 屏幕物理像素 | 父元素的 font-size | 根元素(html) 的 font-size |
| 计算方式 | 绝对值,1px=1像素 | 1em = 父元素字体大小 | 1rem = 根元素字体大小 |
| 嵌套影响 | 无影响 | 会累积叠加(层层相乘) | 不受嵌套影响 |
| 响应式 | 固定不变 | 随父元素变化 | 随根元素变化 |
| 使用场景 | 边框、细线、精确控制 | 组件内部相对尺寸 | 全局布局、字体、间距 |
二、详细对比与示例
1. px(像素)
- 绝对单位,1px对应屏幕上的一个物理像素点
- 固定不变,不受父元素或根元素影响
- 最直观,但缺乏灵活性
/* 无论父元素或根元素如何变化,10px永远是10像素 */
.box {
font-size: 14px; /* 永远是14px */
padding: 10px; /* 永远是10px */
border: 1px solid #000; /* 边框通常用px保持精确 */
}
2. em(相对父元素)
- 相对单位,1em = 父元素的字体大小
- 具有继承性,会形成"叠加效应"
- 适合组件内部的相对比例
.parent {
font-size: 20px; /* 父元素字体20px */
}
.child {
font-size: 1.5em; /* 30px = 20px × 1.5 */
padding: 2em; /* 60px = 30px × 2 (注意:基于自己的30px!) */
margin: 0.5em; /* 15px = 30px × 0.5 */
}
em的"叠加陷阱"示例
/* 多层嵌套时,em会不断相乘 */
.level1 { font-size: 1.5em; } /* 假设根是16px,这里24px */
.level2 { font-size: 1.5em; } /* 36px = 24px × 1.5 */
.level3 { font-size: 1.5em; } /* 54px = 36px × 1.5 */
/* 实际大小比预期大很多! */
3. rem(root em)
- 相对单位,1rem = 根元素(html)的字体大小
- 不受嵌套影响,保持统一比例
- 适合全局布局和响应式设计
/* 通常在:root或html设置基准大小 */
html {
font-size: 16px; /* 默认,1rem = 16px */
}
.container {
font-size: 2rem; /* 32px = 16px × 2 */
padding: 1rem; /* 16px */
margin: 0.5rem; /* 8px */
}
/* 不受父元素影响示例 */
.parent {
font-size: 30px; /* 父元素改变 */
}
.child {
font-size: 1rem; /* 仍是16px,不受父元素影响 */
width: 20rem; /* 320px = 16px × 20 */
}
三、实际场景对比
场景1:字体大小设置
/* 方式1:使用px - 固定不变 */
body { font-size: 14px; }
.title { font-size: 24px; }
/* 方式2:使用em - 相对父级 */
body { font-size: 14px; }
.section { font-size: 1.2em; } /* 16.8px */
.section .title { font-size: 1.5em; } /* 25.2px (相对16.8px) */
/* 方式3:使用rem - 相对根级 */
html { font-size: 16px; }
.title { font-size: 1.5rem; } /* 24px */
.subtitle { font-size: 1.125rem; } /* 18px */
场景2:间距设置
/* 统一使用rem控制全局间距 */
:root {
--spacing-xs: 0.5rem; /* 8px */
--spacing-sm: 1rem; /* 16px */
--spacing-md: 1.5rem; /* 24px */
}
.card {
padding: var(--spacing-md);
margin-bottom: var(--spacing-sm);
}
/* 组件内部使用em保持比例 */
.alert {
font-size: 14px;
padding: 1em; /* 14px,随字体大小变化 */
border-radius: 0.5em; /* 7px,保持圆角比例 */
}
四、响应式设计中的应用
rem实现响应式缩放
/* 移动优先:基础字体较小 */
html {
font-size: 14px; /* 移动端 */
}
/* 平板 */
@media (min-width: 768px) {
html {
font-size: 15px;
}
}
/* 桌面 */
@media (min-width: 1024px) {
html {
font-size: 16px;
}
}
/* 所有使用rem的元素会自动缩放 */
.header {
height: 4rem; /* 移动端:56px, 桌面:64px */
padding: 1rem; /* 自动适应 */
}
em在组件响应式中的应用
/* 按钮组件:内部使用em,整体用rem控制 */
.button {
font-size: 1rem; /* 跟随全局 */
padding: 0.75em 1.5em; /* 内边距随字体缩放 */
border-radius: 0.5em; /* 圆角保持比例 */
}
/* 媒体查询中调整组件基础大小 */
@media (max-width: 768px) {
.button {
font-size: 0.875rem; /* 变小一点 */
/* padding和border-radius会自动按比例调整 */
}
}
五、最佳实践建议
推荐用法
- 字体大小:主用
rem,少数情况用em
:root { font-size: 16px; }
body { font-size: 1rem; } /* 16px */
h1 { font-size: 2.5rem; } /* 40px */
small { font-size: 0.875em; } /* 相对于父元素 */
- 间距和布局:主用
rem,组件内用em
.container {
padding: 2rem; /* 全局统一 */
}
.card {
font-size: 1rem;
padding: 1em; /* 组件内相对 */
margin-bottom: 1.5rem; /* 全局相对 */
}
边框、阴影:用 px 保持精确
.box {
border: 1px solid #ccc; /* 细线用px */
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
避免的问题
- em嵌套问题:不要在多层嵌套中都用em控制字体
/* 避免这样! */
.level1 { font-size: 1.2em; }
.level2 { font-size: 1.2em; } /* 已经是1.44em了 */
/* 应该这样 */
.level1 { font-size: 1.2rem; }
.level2 { font-size: 1.2rem; } /* 保持1.2rem */
- 混合单位计算:注意calc()中的单位一致性
/* 错误:单位不匹配 */
width: calc(100% - 20px); /* OK,%和px可以计算 */
/* rem和em混合要小心 */
padding: calc(1rem + 2em); /* 只有当1rem和2em基准相同时才有效 */
六、现代CSS的替代方案
CSS变量 + rem
:root {
--font-base: 16px;
--spacing-unit: 0.5rem; /* 8px */
/* 响应式调整 */
@media (min-width: 768px) {
--font-base: 18px;
--spacing-unit: 0.75rem;
}
}
html {
font-size: var(--font-base);
}
.component {
padding: calc(var(--spacing-unit) * 2); /* 16px或24px */
}
clamp() 函数
/* 响应式字体:最小值1rem,理想值2.5vw,最大值2.5rem */
h1 {
font-size: clamp(1rem, 2.5vw, 2.5rem);
}
总结选择策略
| 情况 | 推荐单位 | 理由 |
|---|---|---|
| 全局布局/间距 | rem | 统一控制,便于响应式调整 |
| 组件内部尺寸 | em | 保持组件内比例协调 |
| 边框/细线 | px | 保持精确,避免缩放变形 |
| 需要固定大小 | px | 图标、某些UI元素 |
| 与字体相关的内边距 | em | 随字体大小自然调整 |
| 媒体查询断点 | em | 基于字体而非像素更可靠 |
现代最佳实践:
- 62.5%技巧:设置
html { font-size: 62.5%; }使1rem = 10px,方便计算 - CSS变量:结合自定义属性管理尺寸系统
- 混合使用:rem为主,em为辅,px用于边框阴影
记住:rem用于全局,em用于局部,px用于精确控制。