Responsive Design With "em" Units

📐 What are "em" units in CSS?
The em unit is a CSS measurement relative to the font size of the element on which it is used. If the element does not have a font-size explicitly set, it is calculated based on the inherited font-size from the nearest ancestor element that does have a font-size. For example, 2em means twice that font size.
Imagine that you had this HTML:
<div class="container">
<p class="child">Hello World</p>
</div>With this CSS applied:
.container {
font-size: 10px;
}
.child {
font-size: 3em; /* 3 times the inherited font-size (10px) */
}This translates into the child's computed font-size being 30px, which is three times the font size of the parent element. This technique is a powerful way to minimize the number of media queries you need to write for responsive typography.
😩 The Hard-Coded Approach (Don't Do This!)
Imagine we were tasked with making a responsive website for mobile, tablet, and desktop viewports, using the following simple markup:
<h1>Hello World</h1>
<p>Nice to meet you.</p>
<small>footnote</small>It would be a pain to have to write individual queries for every single element, repeatedly overriding their pixel values at every breakpoint.
Here is how you are forced to write your CSS without using relative units:
/*** Booooo this takes forever ***/
/* MOBILE First Design */
h1 { font-size: 30px; }
p { font-size: 10px; }
/* TABLET Media Query */
@media (min-width: 768px) {
h1 { font-size: 60px; }
p { font-size: 20px; }
}
/* DESKTOP Media Query */
@media (min-width: 1024px) {
h1 { font-size: 90px; }
p { font-size: 30px; }
}This doesn't scale well in larger applications. Imagine if you had even just ten more CSS rules. That would be 30 rules to maintain. In addition to the higher maintenance cost, it's very easy to make a mistake and enter the incorrect font size since you're hard-coding all the values.
✅ The em Unit Solution
If your design requirements are simple enough, you can let em units do all the work and just change the font size once on an ancestor element, letting the change propagate down.
The CSS with em Units:
/* MOBILE */
.container {
font-size: 10px;
}
/* TABLET */
@media (min-width: 768px) {
.container {
font-size: 20px;
}
}
/* DESKTOP */
@media (min-width: 1024px) {
.container {
font-size: 30px;
}
}
h1 {
font-size: 3em;
}
p {
font-size: 1em;
}The Power of Propagation
The nearest ancestor element for all three text elements is .container. We’ve added a single font-size rule to each text element using the em unit. Now, all we need to do is change the font-size on .container, and that change will automatically propagate and scale all descendant typography.
Here's a look at the resulting computed pixel values for each viewport size:
Viewport | .containerFont Size | h1 (3em) | p (1em) |
|---|---|---|---|
Mobile | 10px | 30px | 10px |
Tablet | 20px | 60px | 20px |
Desktop | 30px | 90px | 30px |
🛑 Any Downsides? (Why you need rem)
This approach might not be flexible enough if your design requirements are even moderately complex, primarily because of the compounding effect. Since an element's em-based font size is calculated relative to its parent's size, nesting elements deeply can lead to unexpected, exponential sizing.
For this reason, many modern CSS developers prefer the rem unit. The rem unit (Root em) is relative only to the font size of the document's root element (<html>). This eliminates the compounding issue and is generally considered the safer default for responsive typography.
In those cases where em or rem alone aren't enough, I recommend using a CSS preprocessor, which offers more powerful utilities through reusable functions. I'll cover that in another post!