- Published on
Mastering CSS Font Size: The Ultimate Guide to `em` vs. `rem`
- Authors
- Name
- Md Nasim Sheikh
- @nasimStg
em
vs. rem
'
'Mastering CSS Font Size: The Ultimate Guide to A comprehensive guide to CSS font-size, diving deep into the differences between absolute (px) and relative (em, rem) units to help you build more scalable, accessible, and maintainable websites.
Table of Contents
- 'Mastering CSS Font Size: The Ultimate Guide to em vs. rem'
- Mastering CSS Font Size: The Ultimate Guide to em vs. rem
- The Foundation: Absolute vs. Relative Units
- Absolute Units: The Unchanging Ruler
- Relative Units: The Chameleon
- The em Unit: The Parent's Child
- The em Compounding Problem
- The rem Unit: The Root's Rule
- The 62.5% Trick: A Modern Best Practice or an Anti-Pattern?
- Practical Strategy: A Hybrid Approach for When to Use What
- 1. Use rem for Global Sizing and Spacing
- 2. Use em for Component-Internal Sizing
- 3. Use px for Values That Should Never Scale
- Beyond em and rem: A Glimpse at Fluid Typography
- Conclusion: Choose Your Units with Purpose
em
vs. rem
Mastering CSS Font Size: The Ultimate Guide to Typography is the bedrock of web design. It’s more than just choosing a pretty font; it's about readability, hierarchy, and user experience. And at the heart of web typography lies a seemingly simple CSS property: font-size
. But ask any seasoned developer, and they'll tell you that the choice of unit for this property—be it px
, em
, rem
, or something else—is one of the most critical decisions you'll make for the long-term health of your stylesheet.
Choosing the wrong unit can lead to a cascade of problems: websites that don't scale, accessibility nightmares for users with visual impairments, and a maintenance headache that grows with every new component you build.
In this guide, we're going to demystify the world of CSS font-size units. We'll start with the basics of absolute vs. relative units, then take a deep dive into the two most powerful relative units in your toolkit: em
and rem
. By the end, you'll not only understand how they work but also have a clear, practical strategy for when and why to use each one.
The Foundation: Absolute vs. Relative Units
Before we can compare em
and rem
, we need to understand the two fundamental categories of units in CSS: absolute and relative.
Absolute Units: The Unchanging Ruler
Absolute length units are fixed and will appear as the same size regardless of the context. They are not relative to anything else in the document.
The most common absolute unit on the web is the pixel (px
).
h1 {
font-size: 32px;
}
p {
font-size: 16px;
}
Pros of px
:
- Predictable: A pixel is a pixel (mostly). It provides pixel-perfect control, which can be appealing for designers who want their vision executed precisely.
- Easy to Understand: The concept is straightforward for beginners.
Cons of px
:
- Accessibility Issues: This is the big one. If a user sets a larger default font size in their browser settings (e.g., due to a visual impairment), text set in
px
will not scale accordingly. This forces users to rely on full-page zoom, which can be a clunky experience. It disrespects the user's preferences. - Poor Scalability: When building a responsive design, using pixels for everything (
font-size
,padding
,margin
) makes it difficult to scale components up or down uniformly. You end up writing complex media queries to adjust dozens of pixel values.
While pixels have their place (we'll touch on that later), they are generally not the right choice for typography and layout spacing.
Relative Units: The Chameleon
Relative units, as the name suggests, get their value from something else. Their size is relative to another length property, which makes them incredibly flexible and powerful for building fluid, accessible designs.
Key relative units include:
%
(percentage): Relative to the same property in the parent element.em
: Relative to thefont-size
of the parent element.rem
(root em): Relative to thefont-size
of the root (<html>
) element.vw
/vh
: Relative to 1% of the viewport's width or height.
For the rest of this guide, we'll focus on em
and rem
, the two workhorses of modern CSS typography.
em
Unit: The Parent's Child
The The em
unit is defined by the font-size
of its nearest parent element. If the parent doesn't have an explicit font-size
set, it inherits it from its parent, and so on, up the DOM tree.
Let's look at a simple example. By default, most browsers set the base font size to 16px
.
<div class="parent">
<p>This is some text.</p>
</div>
.parent {
/* 1.25 * 16px (default) = 20px */
font-size: 1.25em;
}
.parent p {
/* 0.8 * 20px (from .parent) = 16px */
font-size: 0.8em;
}
In this case, the p
tag's font size is relative to its parent, .parent
. This makes em
units excellent for creating components that should scale proportionally.
A key insight: The em
unit is not just for font-size
. When used for other properties like padding
, margin
, or width
, it is still relative to the element's own calculated font-size
.
.button {
font-size: 18px;
/* padding will be 0.5 * 18px = 9px */
padding: 0.5em 1em;
}
.button--large {
font-size: 24px;
/* padding automatically scales! 0.5 * 24px = 12px */
}
This is powerful! By changing just the font-size
on .button--large
, the padding scales perfectly along with it. This makes creating component variations a breeze.
em
Compounding Problem
The This parent-relative nature, however, is also the em
unit's greatest weakness. In deeply nested structures, em
units can have a compounding effect that is difficult to predict and manage.
Consider a nested list for comments or navigation:
<article>
<h2>Comments</h2>
<ul>
<li>Level 1 Comment
<ul>
<li>Level 2 Reply
<ul>
<li>Level 3 Reply - Oh no!</li>
</ul>
</li>
</ul>
</li>
</ul>
</article>
article {
font-size: 16px;
}
/* Let's try to make nested list items smaller */
ul {
/* Each nested ul will be 90% of its parent's font-size */
font-size: 0.9em;
}
Let's calculate the font sizes:
article
:16px
(our base)- Level 1
li
: Inherits16px
fromarticle
. - Level 2
ul
:0.9em
of its parentli
's font-size =0.9 * 16px = 14.4px
. - Level 2
li
: Inherits14.4px
. - Level 3
ul
:0.9em
of its parentli
's font-size =0.9 * 14.4px = 12.96px
. - Level 3
li
: Inherits12.96px
.
The text gets progressively and uncontrollably smaller with each level of nesting. This compounding effect makes it nearly impossible to maintain a consistent typographic scale across a complex application.
rem
Unit: The Root's Rule
The Enter the rem
unit, which stands for "Root EM". It was created specifically to solve the compounding problem of em
s.
The rem
unit is not relative to the parent element. Instead, it is always relative to the font-size
of the root element, which is the <html>
tag.
html {
/* This is the base for all rem units on the page */
/* Most browsers default to 16px */
font-size: 100%; /* or 16px */
}
h1 {
/* 2 * 16px = 32px */
font-size: 2rem;
}
p {
/* 1 * 16px = 16px */
font-size: 1rem;
}
.sidebar {
/* 0.875 * 16px = 14px */
font-size: 0.875rem;
}
Let's revisit our nested list example, but this time using rem
:
<article>
<ul>
<li>Level 1 Comment</li>
<li>Level 1 Comment
<ul>
<li>Level 2 Reply</li>
<li>Level 2 Reply
<ul>
<li>Level 3 Reply</li>
</ul>
</li>
</ul>
</li>
</ul>
</article>
html {
font-size: 16px;
}
/* Set a consistent font-size for all list items, regardless of nesting */
li {
font-size: 1rem; /* Always calculates to 16px */
}
/* Or maybe we want a specific size for a component */
.comment-thread li {
font-size: 0.9rem; /* Always calculates to 14.4px, no compounding! */
}
With rem
, the font-size
of every element is predictable. It only depends on one value: the root font-size
. This brings back the predictability of px
while retaining the scalability and accessibility benefits of relative units. If a user changes their browser's default font size, the <html>
element's font-size
changes, and your entire rem
-based layout and typography scale up or down perfectly.
The 62.5% Trick: A Modern Best Practice or an Anti-Pattern?
For years, a popular technique circulated in the development community to make rem
calculations easier. It's known as the "62.5% trick."
The logic is this: The default browser font size is 16px
. If we set the root font size to 62.5%
of that, we get:
16px * 0.625 = 10px
By setting html { font-size: 62.5%; }
, you make 1rem
equal to 10px
. This simplifies the math significantly:
1.6rem
=16px
2.4rem
=24px
0.8rem
=8px
It seems like a clever solution. However, this is now widely considered an anti-pattern and a bad practice for accessibility.
Why? Imagine a user with low vision has gone into their browser settings and set their default font size to 20px
to make text more readable. If your CSS contains html { font-size: 62.5%; }
, you are overriding their explicit preference. You've now forced their base font size down to 20px * 0.625 = 12.5px
, making the site less accessible for them, not more.
The Modern, Accessible Alternative:
Respect the user's settings. Leave the root font size at its default.
html {
/* Let the browser and user control the base font size. */
/* 100% is the default, so you don't even need this declaration. */
font-size: 100%;
}
"But the math is harder!" you might say. True, dividing by 16 isn't as easy as dividing by 10. But we have tools to solve this:
- Use Comments: Simply document the pixel equivalent in your code.
p { /* 18px / 16px = 1.125rem */ font-size: 1.125rem; }
- Use CSS
calc()
: Let the browser do the math.p { font-size: calc(18 / 16 * 1rem); }
- Use a Sass/Less Function: If you're using a preprocessor, this is the cleanest solution. Create a function to handle the conversion.
// Sass (SCSS) function @function rem($pixels, $context: 16) { @return ($pixels / $context) * 1rem; } p { font-size: rem(18); } h1 { font-size: rem(48); }
These modern approaches give you the best of both worlds: developer convenience and, most importantly, a fully accessible and user-respecting experience.
Practical Strategy: A Hybrid Approach for When to Use What
So, the ultimate question is: which unit should you use? The best strategy isn't to pick one and use it for everything. It's to use each unit for what it does best.
Here is a practical, modern rulebook:
rem
for Global Sizing and Spacing
1. Use Use rem
for any property that should scale with the root font size, creating a globally consistent and accessible UI.
- Typography: Set your base
font-size
on thebody
inrem
, and define your entire typographic scale (h1
,h2
,p
, etc.) usingrem
. - Layout Spacing: Use
rem
formargin
andpadding
on major layout components like headers, footers, sections, and grids. This ensures that the whitespace in your layout scales with the text size. - Component Size: Define the
width
,height
,max-width
of major components inrem
.
body {
font-size: 1rem; /* 16px base */
line-height: 1.5;
}
h1 {
font-size: 3.052rem; /* ~49px */
margin-bottom: 2rem;
}
.main-content {
padding: 2rem;
}
em
for Component-Internal Sizing
2. Use Use em
for properties inside a component that should scale relative to that component's own font-size
.
- Button Padding: As shown earlier,
padding
inem
allows a button to grow or shrink based on itsfont-size
. - Icon Sizing: Size an icon within a text element using
em
so it always matches the surrounding text. - Element-Specific Line Height: If a specific heading needs a tighter
line-height
than the body, setting it inem
(line-height: 1.2em;
) makes it relative to the heading's ownfont-size
.
.card {
font-size: 0.9rem; /* Set the card's base font size */
padding: 1.5em; /* This padding is relative to the card's 0.9rem font-size */
}
.card__title {
font-size: 1.2em; /* This is relative to the card's font-size, NOT the root */
margin-bottom: 0.5em; /* This margin is relative to the title's font-size */
}
In this card example, if we decide to make the entire card bigger (.card { font-size: 1.1rem; }
), the padding and title size will scale up proportionally and automatically!
px
for Values That Should Never Scale
3. Use Is there ever a place for px
? Yes, for tiny, specific values that you want to remain constant regardless of user settings.
- Borders:
border: 1px solid black;
is a perfect use case. You almost always want a border to be a crisp, single pixel line. - Box Shadows: The offset and blur values in
box-shadow
are often best defined inpx
for fine-tuned control.
em
and rem
: A Glimpse at Fluid Typography
Beyond Once you've mastered rem
and em
, you can explore even more advanced techniques. Modern CSS offers viewport units (vw
, vh
) and functions like clamp()
that allow for truly fluid typography.
Fluid typography scales smoothly with the viewport size, not just in steps at media query breakpoints.
Here's a quick look at the clamp()
function:
font-size: clamp(MINIMUM_VALUE, PREFERRED_VALUE, MAXIMUM_VALUE);
MINIMUM_VALUE
: The smallest the font size can be.PREFERRED_VALUE
: A flexible value, usually involving a viewport unit likevw
.MAXIMUM_VALUE
: The largest the font size can be.
h1 {
/*
Min size: 2rem (~32px)
Scalable size: 4vw (4% of viewport width)
Max size: 4rem (~64px)
*/
font-size: clamp(2rem, 1rem + 4vw, 4rem);
}
This h1
will have a base size of 2rem
on small screens. As the screen gets wider, it will grow proportionally with the viewport width (1rem + 4vw
). It will stop growing once it reaches 4rem
. This creates a perfectly fluid heading without complex media queries. Notice how it combines a rem
unit (for accessibility) with a vw
unit (for fluidity).
Conclusion: Choose Your Units with Purpose
The journey from px
to em
and rem
is a journey toward becoming a more thoughtful, professional front-end developer. It's about moving from a rigid, fixed-width mindset to a flexible, user-centric one.
Let's recap the strategy:
rem
is your default: Use it for typography, global spacing, and most layout dimensions. It provides consistency and respects user accessibility settings.em
is for component-specific scaling: Use it for properties likepadding
ormargin
inside a component that should be relative to the component'sfont-size
, not the global one.px
is for fixed details: Use it sparingly for things like borders and shadows that should never scale.
By mastering these units and applying them with purpose, you'll build websites that are not only beautiful and responsive but also more accessible and far easier to maintain in the long run. You're not just styling a website; you're crafting a resilient and adaptable user experience.