When to use rems, ems, px, or whatever else in CSS
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
, andflex-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
rem
s 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/). em
s 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 default
font-size
of16px
. This is set at the root element (aka thehtml
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 rem
s are computed relative to the root font size, sizing elements in rem
s means that content will scale proportionately. Thus, in almost all cases I recommend using rem
s. This applies to font-size
, margin
, padding
, min-width
, and so on.
Any drawbacks to rems?
I’ve read that using rem
s 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 usingrem
s 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 rem
s 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 rem
s.
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-heigh
as 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