CSS: How to Choose Between rem, em, and px
Have you ever run into this? Font sizes look perfect on a small screen but become absurdly large on a big one. Or you change the root font size and the entire page layout falls apart. These issues all come down to your choice of CSS units. CSS units seem simple, but using the wrong one in the wrong place can make responsive design painful.
TLDR
| Scenario | Recommendation |
|---|---|
| Font size | rem |
| Layout width | %, vw |
| Spacing (margin/padding) | rem / em |
| Borders, shadows | px |
| Full-screen hero section | vh |
Relative Units: rem vs em
rem: Relative to the Root Element
html {
font-size: 16px; /* 默认值 */
}
h1 {
font-size: 2rem; /* 2 * 16px = 32px */
}
p {
font-size: 1rem; /* 1 * 16px = 16px */
}
Why recommend rem?
-
Change one place, apply globally
/* 用户设置了大字号,rem 自动响应 */ html { font-size: 18px; /* 所有 rem 都自动变大 */ } -
No side effects
/* 嵌套多层时,em 会逐层累积,rem 不受影响 */ .parent { font-size: 2em; /* 子元素会是 2 * 2em = 4em */ } .child { font-size: 1rem; /* 永远是 16px,不受父元素影响 */ }
em: Relative to the Parent Element
.parent {
font-size: 20px;
}
.child {
padding: 1em; /* 1 * 20px = 20px */
margin: 2em; /* 2 * 20px = 40px */
}
Scenarios where em fits well
/* 按钮:保持和文字成比例的内边距 */
.btn {
padding: 0.5em 1em;
/* 字体大 → 按钮大,字体小 → 按钮小 */
}
Percentage: %
Relative to the parent element’s dimensions.
.container {
width: 80%; /* 父元素宽度的 80% */
}
.child {
width: 50%; /* container 宽度的 50% */
}
Common applications
/* 居中布局 */
.box {
width: 80%;
margin: 0 auto;
}
/* 响应式图片 */
img {
max-width: 100%;
height: auto;
}
Viewport Units: vw / vh
Relative to the browser’s visible area.
/* 全屏 hero 区 */
.hero {
height: 100vh; /* 100% 视口高度 */
display: flex;
align-items: center;
justify-content: center;
}
/* 响应式文字 */
h1 {
font-size: 5vw; /* 随视口宽度缩放 */
}
Practical tip: clamp the range
/* vw 太大时会失控,用 clamp 限制 */
h1 {
font-size: clamp(24px, 5vw, 64px);
/* 最小 24px,最大 64px,中间随 vw 变化 */
}
Absolute Unit: px
A fixed value that does not change relative to anything.
Suitable scenarios
/* 边框 - 像素级精确 */
.card {
border: 1px solid #ddd;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* 分割线 */
.divider {
height: 1px;
background: #eee;
}
/* 小间距微调 */
.icon {
margin-right: 4px;
}
Use px for fonts with caution
/* ❌ 响应式差,小屏手机上显得太大 */
body {
font-size: 16px;
}
/* ✅ 响应式好,尊重用户设置 */
body {
font-size: 1rem;
}
Selection
Typical scenario comparison
| Scenario | Recommendation | Reason |
|---|---|---|
| Page root font size | rem | Unified control |
| Text inside components | rem | Scales correctly even in standalone components |
| Button padding | em | Keeps proportion with text |
| Card width | % | Adapts to container |
| Modal centering | flex / grid | More reliable |
| Hero full screen | vh | Directly fills the viewport |
| Fixed header | px or rem | No need for responsiveness |
Complete example
:root {
/* 统一管理字号 */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.25rem; /* 20px */
--font-size-xl: 1.5rem; /* 24px */
--font-size-2xl: 2rem; /* 32px */
}
body {
font-size: var(--font-size-base);
line-height: 1.6;
}
h1 {
font-size: var(--font-size-2xl);
}
.card {
padding: 1.5rem;
margin-bottom: 1rem;
}
.btn {
padding: 0.5em 1.5em;
border: 1px solid currentColor;
}
Summary
- Use rem for font sizes: easy to maintain and respects user preferences
- Use rem/em for spacing: keeps proportion with font size
- Use % / vw for layout: responsive and adaptive
- Use px for borders and shadows: precise control
- Use vw/vh for full-screen sections: simple and direct
Remember: the core of responsive design is “proportion” rather than “fixed values.” Using relative units well makes page scaling feel more natural.