Designing with Rem and Em: Creating Harmonious Typography

Styling with relative units is way easier than absolute units like px, and that's a hill I'm willing to die on. Don't believe me? Let me introduce you to the magical world of 'em' and 'rem' units!

In this article, we'd be comparing relative to absolute units. Relative units are units that do not have fixed values. They are calculated based on some other value. These units allow for more flexible and responsive designs, as they adjust relative to the element they are based on, usually a parent element. Some examples are rem, em, %, vh, vw, etc. Absolute units on the other hand have fixed values. They are more rigid and could easily cause design breaks on smaller screen sizes when used without media queries. Some examples are px, pt, in, cm, mm etc.

Making REM easier for you

REM (root -em height) is a measure of the root element, that is, the HTML element. It is the default size which depends on the browser being used. The value is 16px in most browsers. So 1rem = 16px, 2rem = 32px, 10rem = 160px and so on. Relative and absolute units work in the same way so if you wanted to set the font size on an element to 40px, you can do some in REM units by mathematically calculating the REM equivalent of 40px. Recall, 1rem = 16px, 40px would be 2.5rem.

This method of calculation can easily become tedious when working with a large code base. So a little trick that makes it easier is to overwrite the default browser font size and set it to 10px instead of 16. To do that, add this code to your CSS file. This is popularly known as the '10px baseline' or 'CSS reset'.

html {
font-size: 10px;
}

That's it and just like magic, all our calculations are now easier! 1rem = 10px, 1.4rem = 14px, 12.7rem = 127px and so on. This code gets the work done but is a terrible approach for accessibility reasons. A user might want to zoom in or out on your webpage and this would cause conflicting styling on your site which may result in the rem-styled elements not responding to the user's zoom attempts.

A way to fix this would be to again find the relative equivalent of 10px in respect to 16px which is the default and considered 100%. So, what percentage of 16px is 10px? You can determine this mathematically to be 62.5%. So it is recommended to set the font size to 62.5% and not 10px so that the user is still able to zoom in and out of the page seamlessly. Note that 62.5% of 16px is the same thing as 10px. We are just using the relative equivalent of 10px.

The em unit

The em unit is relative to the size of a parent element, that is, the parent of whatever element you're setting it on. So if the font size of an element is 16px, setting the font size of its child element to 1em would give it a font size of 16px also. Setting it to 2em would give it a font size of 32px and so on. Unlike the rem where everything is relative to the default base font size, the em unit is relative to the closest parent element.

You can also apply decimals here like 1.2em which would be 1.2 times the size of the parent element or the root element in the absence of a parent element.

The beautiful thing about relative units apart from their responsiveness, is their fluidity. You can easily scale up or down your entire webpage by adjusting the default font size or just one parent element. You wouldn't need to change every single font styling unlike with absolute unit. And I keep saying font size but these units can be applied to other sizing too like margins and paddings!

Should I use rem or em?

Now you might be thinking, 'So should I use rem or em?' Let's consider different use cases like paddings and margins, widths and height, media queries etc.

Paddings

We've established that using rem values for styling means they will scale with the user's default browser font size. While this is great for ensuring consistent typography, it may not be desirable for all elements on your website.

Should all elements increase in size as the user scales up their browser's default font size? And this is the question you need to ask when you wonder which unit to use.

When you set padding, you don't want it to increase in size because the user is trying to read bigger letters. In fact, if it increases as the text increases, that would leave little space left for the text and you might end up having a box with lots of space around it and only one or two words per line.

The same applies to borders. It wouldn't make sense to increase the size of element borders because the user is trying to scale up their font. It would be better to declare those values with the pixel unit.

Margins

What about when styling margins? What kind of unit do we want to use? While horizontal margins, similar to padding would reduce the available space for text and reduce the text to one-liners when the user scales up, the same is not so for top and bottom margins. They create white space between elements to increase readability and reduce strain on the eyes. We want the margins to increase however much the user scales up the font size so that the text remains segmented into blocks.

We want this property to scale up or down evenly along with the user's font sizing so it makes send to use a relative unit like rem.

Widths and Heights

This one can be a little bit tricky. The unit to use depends on the amount of space available and the layout you have in mind. Imagine you want to set a width on an element that contains some text, say a button, how do you want it to react to the user scaling up the font size? Do you want the text to wrap onto new lines as the font increases, leading to a taller element? Or would you prefer the element to widen as much as possible to accommodate the larger font size?

Most time, we want the element to grow wider with the text. It only makes sense. Having a button, for example, grow taller instead of wider would be aesthetically unpleasing. Also, remember what we discussed in padding? There might end up being only a few words of text per line which would be unpleasant to read.

So most times, we want to set the width with rem and set the height with pixels to preserve the element's proportions. You can also err on the side of caution by setting the max-width on that element to 100% to prevent it from breaking the design if the user scales all the way up!

Media Queries

So, let's consider this last one. Should we use pixels or rem units for media queries? Let's reason and see the implications. If I have this code @media (min-width: 50rem) {}, and perhaps a visitor to my site has scaled up their font-size x2, that means 1rem would then equal 20px (assuming I have set the default base size to 62.5% as discussed earlier). This means that my breakpoint would only be activated at 1000px! Even if they're on a desktop, the user would only experience the desktop view when the screen size is greater than 1000px (instead of the usual approximate 426px).

Is this a good thing? Most times, yes! When the font is increased, it means there is less available space. We don't want to have to cram everything on the page even when the user has doubled their font size, this might even cause the design to break. Instead, we want to maximize the available space by collapsing things like side articles and navigations just like we would do on a mobile screen.

Conclusion

We've learnt a lot from different types of units to their comparisons and use cases. But even with all these, it could still get a bit confusing where to use what, and I get confused at times. The best thing to do in cases where it isn't so obvious which to use is to test it.

Change your browser's default size to different settings and check out the website again to get a feel of what a user would experience while navigating your website in zoom mode. Then try both cases, rem and pixels. It should become immediately clearer which to use.

Overall, the best way to get better at writing CSS is by constant practice. Now I know CSS is the bane of many a developer, but it's simply something you must excel at, especially as a frontend developer. Over time, you'd get better at knowing the right units to use.