px vs em vs rem vs …
In this article I will try to summarize the pros and cons of using px vs em vs rem.
First of all let’s clarify some definitions.
A pixel is the atomic division of the screen (or media support) and it consists of red, green and blue sub-pixels. But this is not a CSS pixel, this is a hardware pixel. A px(pixel) or CSS pixel is actually a reference pixel and it’s a relation between visual angle and distance and device pixel density. I won’t go into details – you can’t find them here. The idea is that a CSS pixel is not always a pixel on a screen, but more like an optical illusion of an atomic division.
A pt(point) is a measurement unit traditionally used in print media (anything that is to be printed on paper, etc.) and equals to 1/72 of an inch.
An em is a measurement unit relative to the font size of the element it refers too. It’s not known what exactly em stands for, but it is believed to come from the letter M (spelled em) of which size usually accommodates all letters in a font.
A rem is a measurement unit relative to the font size of the root element. It is very much alike em, even the name says it so – root em, but it has a different point of reference.
A %(percent) is a measurement unit relative to the font size of the element it refers too.
px and pt are absolute unit lengths and em, rem and % are relative unit lengths. What’s the biggest difference between relative and absolute? Relative is scalable according to their reference point (current element or root element) as opposed to absolute which does not scale at all.
Then what should we use? What’s the “perfect” measurement unit? Well, like in the real world, there’s no perfect. So, you have to consider a few things before making a decision. And remember that you can use these units for everything: margins, width and height of elements, image sizes, paddings, media queries etc.
Pixel perfect design versus support for a plethora of devices
If you design a printed report (yes, it’s possible with HTML :)) and you want to look beautifully on paper, then use pt. That one is a typographical measurement and it will be the most appropriate one.
If you want to design a static page that will render beautifully (I mean pixel perfect) on one device only, then use px. But then it will render on one device only and far from beautifully on other devices. It could still be useful if you want to design for example a beautiful static ad to be used in desktop browsers.
Why? First of all, because of what I said earlier, pixels are not actually atomic subdivision of a screen, but rather optical reference units.
Can I patch this somehow? Kind of. Nowadays, browsers have a zoom feature, but this approach has two downsides. You have to rely on user to zoom in-out your page. You can also set programatically a zoom (with CSS zoom or transform/scale), but you have to know the exact value for each device. And this will not mean that your page will render beautifully, but rather that it will fit. And then it still could be too small (if you designed it on a larger device) or too large to be visible.
When should you use relative measurements, like em, rem or %? When you want to create web applications (which consists of dynamic pages) with support on different devices. But there’s a downside here too – you could lose some of that pixel perfect look. There is an old concept here, back from the days of Netscape Navigator, liquid layout, which I think it still can suit most needs. The idea is to develop a layout that can easily fit in different screen resolutions, mostly accomplished by using relative positioning and relative sizes instead of absolute ones. I wrote about this in a previous post.
Let me clarify with an example. Let’s suppose we have a paragraph with a padding of one character. Supposing you have a font size of 10px, this will be translated in pixels like this:
p { padding: 10px; }
or with em/rem like this
p { padding: 1em; }
But if the font size changes to 24px, the second case will scale as designed as opposed to the first case when the padding will become just too small (less than half of a character)
Browser text size and accessibility
Web Content Accessibility Guidelines defines the success criteria for making a web page accessible. I would like to refer here especially to SC 1.4.4 which refers to the capability of a web page to be readable (I would say viewable) on different text sizes. The recommended techniques for doing so are to use percent, em or named font sizes. Please keep in mind that these techniques are just recommendation, they’re not necessary.
To be more clear I will turn to a common browser feature – setting text size. I see this kind of feature especially useful on e-readers, but also on mobiles. And now take the example above with the padding. If a user sets the text font to a larger size, that padding will become just too subtle to distinguish beteween paragraphs. Or just imagine an emoji image, that will become less than half of the text size and screw up the entire alignment. I know, I know you could still use icon fonts and special characters for emojis, but I was just making a point about an inline image.
If web accessibility is not a concern for your users, then px is as good.
Floating point precision
All these CSS units, either relative or absolute, are capable of handling floats. Yes, 0.5px could actually make sense. Remember that a pixel is not a hardware pixel, but an illusion and it could actually represent 1 or 2 hardware pixels on a device with DPR of 2 or 4. Here the winner are relative units like em, rem or % because they provide better support for floating point precision.
Maintainability
It’s clearly, even from the example above, why CSS based on relative unit measurements are easier to maintain than the ones based on absolute ones. If you change in one place, everything else will scale automatically. If you use absolute units you have to change everywhere.
Nowadays, SASS(SCSS) has become a de-facto standard for developing CSS, especially in web applications. And if you use semantic CSS sizes, which I would recommend it anyway (I already gave you this blog post) this could be solved.
How does this translate in code? Instead of using padding: 16px
just define a SCSS variable $medium: 16px
and use that one padding: $medium
Every time you change the $medium
value, everything will be updated. Keep in mind that too many sizes or size with names not semantically chosen will just clutter your code and increase maintainability in time.
Remember that using Sass does not solve any of the issues above.
Media queries – are they special?
What should you use for CSS media queries? To help you make a decision I will translate this into plain English. Let’s say you want to make a decision between screen sizes, how would you like to say: “I want option A if the screen can fit 80 characters and option B for more” or “I want option A if the screen can fit 600 optical illusions of a pixel or option B for more”? As you guessed it first option is for relative(em or rem) and second is for absolute(px).
Relative, but root or contextual?
Now, if you decided for relative units, what should you use em or rem?
Well, again, your decision. But I will try to simplify it for you with few examples. Let’s say that you have a reference to a footnote, implemented by the sup
tag. How do you want this to be rendered? Always with the same size or relative to the neighboring text? Let’s suppose that the heading has a double font size that the root one (h1 { font-size: 2rem; }
). Do you want the footnote reference to be doubled too or you just want it as the same size as in paragraph? If you go for the former, use em (sup { font-size: 0.6em; }
) or use rem (sup { font-size: 0.6rem; }
) for the latter.
Now taking the heading in the example above. If you place it in the footer, do you want it the same size as the one in the content, or smaller according to the footer font size? If you want it smaller, then drop the rem as in the above example and use em instead.
Let’s consider a more complex example, some extra information paragraph implemented with the aside
paragraph. Do you want this to render the same all over your page or to scale, let’s say scale down if you include it in the footer? The answer is simple – rem for first option, em for second.
It’s also an option to combine these two.
Fortunately, even though it is a more recent unit, rem has support in all modern browsers. So this is not an issue.
Conclusions
There’s no perfect measurement unit to be used in your pages and you’ll see lot of examples for both. There are a lot of advocates for the relative ones, just because responsive web and support for different devices and browsers has become a priority nowadays. I believe it’s essential to understand the differences, pros and cons between them and then make a decision. Also choosing a combination of these is also a viable option.