Introduction
One of the questions I had when learning CSS was: "Should I use px, em, or rem?" They all seem to do the same thing – set the size of elements. But understanding when to use each one can significantly improve your CSS and make your designs more maintainable and accessible.
The Basics
Let's start with what each unit actually means:
Pixel (px)
- Absolute unit
- Fixed size that doesn't change
1pxis always1px
.element {
font-size: 16px; /* Always 16 pixels */
padding: 20px; /* Always 20 pixels */
}
Em (em)
- Relative unit
- Relative to the parent element's font-size
- Can compound (stack) through nested elements
.parent {
font-size: 16px;
}
.child {
font-size: 2em; /* 2 × 16px = 32px */
padding: 1em; /* 1 × 32px = 32px (uses own font-size!) */
}
Rem (rem)
- Relative unit
- Relative to the root element's (html) font-size
- Does NOT compound through nested elements
html {
font-size: 16px; /* Root font-size */
}
.element {
font-size: 2rem; /* 2 × 16px = 32px */
padding: 1rem; /* 1 × 16px = 16px */
}
The Compounding Problem with Em
Here's where em can get tricky:
html {
font-size: 16px;
}
.parent {
font-size: 1.5em; /* 1.5 × 16px = 24px */
}
.child {
font-size: 1.5em; /* 1.5 × 24px = 36px (compounds!) */
}
.grandchild {
font-size: 1.5em; /* 1.5 × 36px = 54px (compounds again!) */
}
This compounding can lead to unexpected sizes deep in your component tree!
When to Use Each Unit
Use Pixels (px) for:
- Borders
.card {
border: 1px solid #ccc; /* Borders should be consistent */
}
- Box shadows
.card {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
- Fixed dimensions you don't want to scale
.icon {
width: 24px;
height: 24px;
}
Why? These elements should remain consistent regardless of font-size settings.
Use Rem (rem) for:
- Font sizes
h1 {
font-size: 2.5rem; /* Scales with user's font-size preference */
}
p {
font-size: 1rem; /* Base font size */
}
- Spacing (margins, padding)
.section {
padding: 2rem 1rem;
margin-bottom: 3rem;
}
- Widths and heights (when appropriate)
.container {
max-width: 60rem; /* Scales with font-size */
}
- Media queries
@media (min-width: 48rem) { /* 768px at 16px base */
.content {
font-size: 1.125rem;
}
}
Why? rem units respect user preferences and scale predictably. This is crucial for accessibility!
Use Em (em) for:
- Spacing relative to element's own font-size
.button {
font-size: 1rem;
padding: 0.5em 1em; /* Scales with button's font-size */
}
.button-large {
font-size: 1.5rem;
padding: 0.5em 1em; /* Padding automatically scales! */
}
- Line height
p {
font-size: 1rem;
line-height: 1.5em; /* Relative to paragraph's font-size */
}
- Components that should scale together
.card {
font-size: 1rem;
}
.card-title {
font-size: 1.25em; /* Relative to .card */
margin-bottom: 0.5em;
}
.card-body {
font-size: 1em;
padding: 1em;
}
Why? em allows you to create components that scale proportionally to their font-size.
Accessibility Matters
Here's why this matters for users:
Many users change their browser's default font-size for better readability. Compare:
/* ❌ Bad - Doesn't respect user preferences */
.text {
font-size: 16px; /* Always 16px, even if user wants 20px */
}
/* ✅ Good - Respects user preferences */
.text {
font-size: 1rem; /* Scales with user's font-size setting */
}
If a user sets their browser font-size to 20px:
pxunits stay the same (inaccessible)remandemscale up (accessible!)
My Recommended Approach
Here's my rule of thumb:
/* Set a base font-size on html (often 16px default) */
html {
font-size: 100%; /* Use percentage to respect browser defaults */
}
/* Use rem for most sizing */
.container {
padding: 2rem;
margin: 1rem;
font-size: 1rem;
}
/* Use em for padding/margin that should scale with font-size */
.button {
font-size: 1rem;
padding: 0.75em 1.5em; /* Scales with button font-size */
border-radius: 0.25em;
}
/* Use px for borders and small fixed values */
.card {
border: 1px solid #ddd;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
Quick Reference Table
| Unit | Best For | Scales With | |------|----------|-------------| | px | Borders, shadows, fixed sizes | Nothing (absolute) | | rem | Font sizes, spacing, layouts | Root font-size | | em | Spacing relative to font-size | Parent's font-size |
Practical Example
Here's a complete button component using all three units appropriately:
.button {
/* Use rem for base font-size */
font-size: 1rem;
/* Use em for spacing that scales with font-size */
padding: 0.75em 1.5em;
border-radius: 0.25em;
/* Use px for border */
border: 1px solid currentColor;
/* Use px for small shadow */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.button-small {
font-size: 0.875rem; /* Padding automatically scales! */
}
.button-large {
font-size: 1.25rem; /* Padding automatically scales! */
}
Conclusion
- Use
remfor most sizing (fonts, spacing, layouts) - Use
emwhen size should relate to element's own font-size - Use
pxfor borders, shadows, and fine details
Remember: Accessibility matters! Using relative units (rem and em) shows that you care about all your users, including those who need larger text.
The best CSS is CSS that works for everyone! 🎉