px、em、rem有什么区别

109 阅读5分钟

这三个是 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会自动按比例调整 */
  }
}

五、最佳实践建议

推荐用法

  1. 字体大小:主用 rem,少数情况用 em
:root { font-size: 16px; }
body { font-size: 1rem; }  /* 16px */
h1 { font-size: 2.5rem; }  /* 40px */
small { font-size: 0.875em; } /* 相对于父元素 */
  1. 间距和布局:主用 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);
}

避免的问题

  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 */
  1. 混合单位计算:注意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用于精确控制