Understanding CSS Relative Units
CSS provides a plethora of options for specifying values. The most familiar and arguably the easiest to understand is the pixel. Pixels are absolute units—they don’t change. However, other units like em and rem are relative. Their value isn’t fixed; it changes based on external factors.
For instance, the value of 2em changes depending on which element (and sometimes even which property) you’re using it on. Naturally, this makes relative units feel a bit more unpredictable and harder to tame than the straightforward pixel.
In this post, we’ll explore the unique value these units bring to CSS, explain how they work, and show you how to master their seemingly chaotic nature.
The Power of Relative Values
In the early days of software development and traditional publishing, developers knew the exact constraints of their medium. A program window might be exactly 400px by 300px, or a sheet of paper exactly 4 inches wide. Developers knew precisely how much space they had.
On the web, however, that luxury doesn’t exist.
The Struggle for Pixel-Perfect Design
In a web environment, users browse on screens ranging from tiny 4-inch phones to massive 30-inch monitors. They can resize browser windows at will. If you hard-code styles based on an “ideal” context, your design breaks the moment that context changes.
For a long time, designers fought this reality by clinging to “pixel-perfect” designs—creating tightly defined containers (like a centered 800px column) and designing within them as if they were printing on paper.
The End of the Pixel-Perfect Era
When smartphones emerged, we could no longer pretend every user had the same experience. We had to abandon fixed-width columns and embrace responsive design. We couldn’t hide from the fluid nature of the web anymore; we had to work with it.
Relative units are the tools CSS provides to handle this fluidity. Instead of setting a font size to a static 14px, you can set it to scale proportionally with the environment.
Understanding em
The em is the most common relative length unit. A single 1em represents the font size of the current element.
Example: Applying em to padding
.padded {
font-size: 16px;
padding: 1em; /* Sets padding on all sides to 16px */
}
In this case, the padding is 1em. Since the font size is 16px, the browser calculates the padding as 16px (1 × 16).
Using em is incredibly useful for properties like padding, height, width, or border-radius. It ensures that if the font size grows (due to user settings or screen size changes), the spacing around it grows proportionally, preserving the visual balance.
Example: Scalable Components
<!-- This will be a small box -->
<span class="box box-small">Small</span>
<!-- This will be a large box -->
<span class="box box-large">Large</span>
.box {
padding: 1em; /* Depends on font size */
border-radius: 1em; /* Depends on font size */
background-color: lightgray;
}
.box-small {
font-size: 12px;
}
.box-large {
font-size: 18px;
}
In the example above, the .box-small will have 12px padding, and the .box-large will have 18px padding. We defined the layout rules once, and they adapted automatically based on the font size context.
The em Font-Size Trap
When you use em for the font-size property itself, it behaves slightly differently. Since it can’t reference its own font size (that would be a circular reference), it looks at the inherited font size from its parent.
If the browser default is 16px, and you set font-size: 1.2em, the calculated size is 19.2px (16 × 1.2).
The trouble starts when you nest elements. If you have a list inside a list, and both use em for font size, the effect compounds.

This “compounding effect” creates the Shrinking Font Problem, where text gets smaller and smaller (or larger and larger) the deeper you nest. This is why many developers dread using em for typography.
Enter rem (Root EM)
Thankfully, there is a better option for typography: rem.
rem stands for Root EM. Instead of being relative to the parent element, rem is always relative to the root element (usually the <html> tag).
No matter where you use it in your document, 1.2rem will always be 1.2 times the root font size. It eliminates the compounding problem entirely.
Specifying font size using rem
:root {
font-size: 16px; /* Browser default */
}
ul {
font-size: .8rem;
}
In this example, the unordered list has a font size of .8rem (12.8px). Even if you nest a list inside another list, the inner list will still be .8rem relative to the root, not the parent. It stays consistent.
Putting It All Together: A Strategy
Rems simplify the complexity of Ems, offering a middle ground between the rigidity of pixels and the fluidity of relative units. But should you use rem for everything?
In CSS, the answer is usually “it depends.”
Here is a improved strategy for managing units:
- Use
remfor font sizes: This keeps your typography predictable and consistent, regardless of nesting. - Use
pixelsfor borders: Usually, you want a fine, crisp line (like1px) that doesn’t scale. - Use
emfor most other properties: Paddings, margins, and border-radius often look best when they scale relative to the text they surround.
Rule of Thumb: When in doubt, use
remfor font size,pxfor borders, andemfor component spacing (padding/margin).
By following this approach, your text remains predictable, but your components effectively “breath” and scale based on their content, creating a much more robust and responsive interface.