Em, Rem, %: The Three Musketeers of CSS Sizing - Are You Using Them Correctly?

Em, Rem, %: The Three Musketeers of CSS Sizing - Are You Using Them Correctly?

Hello everyone, it's me, your coding companion! Today, we're going to "decode" three relative sizing units that are familiar yet often confusing in CSS: em, rem, and %. If you're still wondering which one to use for which scenario, this article is for you!

In the era of responsive design, using relative units instead of fixed px is a mandatory requirement for your website to look good on all screen sizes. But each unit has its own "personality," and understanding them will help you write much more efficient and maintainable CSS.

em: The "Child Follows Parent" Unit

Imagine em as a child who is very obedient to their parents. Its size will depend on the font-size of its direct parent element.

  • If the parent element does not define a font-size, it will inherit from its grandparent, and so on, until a defined value is found.
  • Example: If the parent's font-size is 16px, then 1em will be equal to 16px. If you set font-size: 1.2em for the child, it will be 1.2 * 16px = 19.2px.

Strengths: Excellent for maintaining proportional sizing of elements within a specific block. For example, in a product card, you want the title and description to have a certain ratio to each other and to the overall size of the card.

Weaknesses: Can easily lead to "compounding" issues. If you have nested em elements, sizes can unexpectedly grow or shrink in an unpredictable way. Take a look at this example:

.parent { font-size: 16px; }.child { font-size: 1.2em; /* 1.2 * 16px = 19.2px */ }.grandchild { font-size: 1.2em; /* 1.2 * 19.2px = 23.04px */ }

See? In just two levels, the size has been "magnified" more than intended.

rem: The "Child Follows Grandparent" Unit (Root em)

Unlike em, rem (short for "root em") is an extremely independent grandchild that only listens to one "grandparent": the font-size of the root html element. Regardless of the font-size of its parent, rem always refers to the font-size of the html element.

  • If you don't define a font-size for html, browsers typically default to 16px. In that case, 1rem = 16px.
  • Golden tip: To make calculations and management easier, many developers often set the font-size for html to 62.5%. Why? Because 62.5% of 16px (default) is 10px. Then, 1rem = 10px, and you can easily convert from px to rem (e.g., 18px to 1.8rem).
html { font-size: 62.5%; /* 1rem = 10px */ }body { font-size: 1.6rem; /* 16px */ }h1 { font-size: 3rem; /* 30px */ }.button { padding: 1.2rem 2rem; /* 12px 20px */ }

Strengths: Extremely easy to manage and predict. Avoids the compounding issues of em. Ideal for defining global font-size for the entire website, margin, padding of major components, and any sizes you want to have consistency and easy adjustability across the page.

%: The "Versatile Relative" Unit

The % (percentage) unit is probably the most familiar, but it also has some small "gotchas" you need to be aware of. It always relies on the size of the parent element, but the "base" for calculating the percentage changes depending on the CSS property you're using.

  • font-size: Similar to em, % will be based on the parent's font-size. If the parent is 16px, a child with font-size: 120% will be 19.2px.
  • width, height: Based on the parent's width or height. Great for creating responsive layouts!
  • padding, margin: This is the point to note! When you use % for padding or margin (whether top, bottom, left, or right), it will always be based on the parent element's width. This can be surprising if you expect padding-top: 10% to be based on the parent's height.
.container { width: 800px; height: 400px; }.box {  width: 50%; /* 50% of 800px = 400px */  height: 50%; /* 50% of 400px = 200px */  padding-top: 10%; /* 10% of 800px = 80px (based on .container's width) */  font-size: 120%; /* 120% of parent's font-size */}

Strengths: Very flexible for fluid layouts and positioning. Especially powerful with width and height.

Weaknesses: The inconsistent behavior of % with padding/margin can be confusing initially.

When to Use What? Quick Summary

For easy recall, here's a quick guide:

  • rem: The top choice for global font-sizes, margins/paddings of major blocks, and general component sizes you want to easily adjust overall. It creates a consistent sizing "system."
  • em: Suitable for internal dimensions of a component, where you want everything to scale proportionally to that component's own font-size. For example, icon size within a button, spacing between small elements in a card.
  • %: Use for fluid layouts (width, height of columns, containers) or when you want an element to scale relative to its parent's size in a clear and intuitive way (except for vertical padding/margin).

Conclusion

Mastering em, rem, and % not only helps you write "better" CSS but is also a crucial step towards creating truly responsive and accessible websites. Try applying them to your next project, and you'll see the difference!

If you have any questions, feel free to leave a comment. See you in the next article!