When to use rems, ems, px, or whatever else in CSS

Eric Masiello
4 min readMar 9, 2020

--

One of the most common questions I hear when discussing CSS best practices is “what unit should I use?” Most of us think and speak in terms of pixels but the px unit is rarely the best choice. Here’s how this all breaks down:

TL;DR

  • Use %, fr, and flex-grow units when setting the size of container elements
  • Use px only when setting the size of ornamental elements for things like hairline borders
  • Omit units altogether when defining line-height
  • Use rems for everything else: font-size, margin, padding, min-width, and media query breakpoints

What’s a rem?

rem, similar to em, is a relative unit. There are great articles out there that explain this in detail so I won’t attempt to regurgitate all that here (see https://zellwk.com/blog/rem-vs-em/). ems can be a bit tricky to use so 9/10 I’ll say stick with rem. In short, here’s how the rem unit works:

  • Browsers have a defaultfont-size of16px. This is set at the root element (aka the html element)
  • The rem unit is a size that is relative to the root element (that’s what the “r” in rem means: root).

This means if want something to be the equivalent of14px, the math is 14/16 = the number of rem units = 0.875rem

Why should I use rems (or ems)?

Relative units are preferred over pixels because they honor user preference and are thus more accessible. Browsers allow users to overwrite the default font size. Changing this value sets the root element’s default font size (font-size: 16px) to a different value. Because rems are computed relative to the root font size, sizing elements in rems means that content will scale proportionately. Thus, in almost all cases I recommend using rems. This applies to font-size, margin, padding, min-width, and so on.

Any drawbacks to rems?

I’ve read that using rems in media queries containing both a min-width and max-width can be problematic due to how browsers inconsistently round non-whole numbers. Personally, it's rare I need to specify both a min and max value in media query so I’m less concerned with this case and still recommend usingrems in media queries. I recommend always building mobile-first which, more often than not, means defining media queries only with min-width.

The “real” (and admittedly small) drawback I see with rems boils down to my initial assertion: we talk about design in pixels. So when scanning code, if I see min-width: 18.75rem, I need to do some quick math to convert that to something I can talk about with non-developers: 300 pixels. We can somewhat remedy this issue by creating a function in your preprocessor of choice that does the computation for us and makes it clearer what’s happening. In SCSS, this could look like this:

When to use px?

The short answer is: rarely. The slightly longer answer is pixels can be used when sizing elements that are ornamental and/or do not need to scale relative to the user’s preferred font size. Borders are a great example. Designers often create hairline borders that are only 1 pixel wide. This likely doesn’t need to scale with a user’s preferred font size.

What about %, fr, flex-grow?

Container elements are those that contain content. Think of them as the big rectangles that typically surface as columns containing text, images, and sometimes other container elements. These typically need some form of width specified in order to achieve the desired layout. Container elements should always be defined using relative values like percentage, the fr unit (for CSS grids), or flex-grow (for flexbox). This ensures the container element expands and contracts relative to the browser viewport dimensions.

When setting the size of elements using relative values, you may want to specify that the element does not shrink any less than some value. In this situation, I specify a min-width using rems.

When should I go unitless?

There is one exception to everything I’ve said up to this point:line-height.

The line-height CSS property sets the height of a line box. It’s commonly used to set the distance between lines of text. On block-level elements, it specifies the minimum height of line boxes within the element. On non-replaced inline elements, it specifies the height that is used to calculate line box height.

Source: https://developer.mozilla.org/en-US/docs/Web/CSS/line-height

It’s best to define the line-heighas a value relative to the font-size of the element. The way to achieve this is by omitting the unit altogether. As an example, if we want the font size of an element to be 14 pixels and the line height to be 20 pixels, the way we compute this:

  • font-size is value in pixels divided by root font size (= 14 / 16)
  • line-height is equal to the desired value in pixels divided by the font size in pixels = 20 / 14

--

--