Back to Basic: Should we use Rem, Em or Pixel?
const x = () =>
<div className="...">
npm install
git commit -m
console.log()
Back to blog
css

Back to Basic: Should we use Rem, Em or Pixel?

Differences between rem, em, and px unit, and some use cases

3 min read
70,894 views views

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
  • 1px is always 1px
css
.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
css
.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
css
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:

css
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:

  1. Borders
css
.card {
  border: 1px solid #ccc; /* Borders should be consistent */
}
  1. Box shadows
css
.card {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
  1. Fixed dimensions you don't want to scale
css
.icon {
  width: 24px;
  height: 24px;
}

Why? These elements should remain consistent regardless of font-size settings.

Use Rem (rem) for:

  1. Font sizes
css
h1 {
  font-size: 2.5rem; /* Scales with user's font-size preference */
}

p {
  font-size: 1rem; /* Base font size */
}
  1. Spacing (margins, padding)
css
.section {
  padding: 2rem 1rem;
  margin-bottom: 3rem;
}
  1. Widths and heights (when appropriate)
css
.container {
  max-width: 60rem; /* Scales with font-size */
}
  1. Media queries
css
@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:

  1. Spacing relative to element's own font-size
css
.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! */
}
  1. Line height
css
p {
  font-size: 1rem;
  line-height: 1.5em; /* Relative to paragraph's font-size */
}
  1. Components that should scale together
css
.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:

css
/* ❌ 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:

  • px units stay the same (inaccessible)
  • rem and em scale up (accessible!)

Here's my rule of thumb:

css
/* 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:

css
.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 rem for most sizing (fonts, spacing, layouts)
  • Use em when size should relate to element's own font-size
  • Use px for 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! 🎉