In this article I'm going to go through a few CSS units for customizing the font-size
of text when building webpages. There are a lot of other units such as pt
, pc
, ex
, etc. I will be focusing on the 3 most popular units; px
, em
, and rem
.
A lot of developers don't usually understand what the differences between these units are (I didn't either, until much later in my career); so I'm going to try to explain them as clearly as possible.
Let's jump right in! π
PX (pixel)
Pixel is probably the most used unit in CSS and are very popular when it comes to setting the font-size
of text on webpages. One pixel (1px
) is defined as 1/96th
of an inch in print media. On computer screens however, they are not usually related to actual measurements like centimeters and inches like you may think, they are just defined to be small but visible. What is considered visible is dependent on the device.
As we know, different devices have different number of pixels per inch on their screens, this is known as pixel density. If we used the number of physical pixels on the screen of a device to determine the size of content on that device, we would have a problem making things look the same across screens of all sizes. That's where device pixel ratio comes in. It's essentially just a way to calculate how much space a CSS pixel (1px
) will take up on the device's screen that will enable it look the same size when compared to another device.
That might have been a lot to take in π , let me simplify a bit. Basically, different screens have different number of pixels (pixel density) and computers perform some calculations to ensure consistency in the size of content being displayed on screens, regardless of the pixel density.
I didn't do justice explaining this as this isn't the primary focus of this article but you can check out this video or this article for a more in-depth explanation.
Moving on...
Let's look at an example below.
A dash of HTML:
<div class="container">
<div>
<h1>This is a paragraph</h1>
<p>
Lorem ipsum, dolor sit amet consectetur adipisicing elit.
Reprehenderit incidunt perferendis iure veritatis cupiditate delectus
omnis at! Officiis praesentium officia, nemo veniam consequatur
nostrum sunt aliquid ipsam, corporis quas quaerat. Lorem ipsum dolor
sit amet consectetur adipisicing elit. Hic quam beatae voluptatibus
amet possimus iure impedit assumenda distinctio aliquid debitis, autem
vel ullam aut, quod corporis ratione atque ducimus dolorum.
</p>
</div>
</div>
A sprinkle of CSS:
* {
font-family: Arial, Helvetica, sans-serif;
}
.container {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container div {
max-width: 500px;
padding: 5px 20px;
border: 1px grey solid;
border-radius: 10px;
}
p {
font-size: 16px;
}
And voila!
The top box is how it looks when displayed on a larger screen like a laptop, and the bottom box is how it looks when displayed on a smaller screen, like a phone.
Notice how the text in both boxes are of the same in size, That's basically how the pixel works. It helps web content (not just text) look the same size across devices.
You can test it out for yourself on codepen here: https://codepen.io/pedoch/pen/vYjEOzO
EM (M)
The EM unit got its name from the uppercase letter 'M' (em) as most CSS units come from typography. The EM unit uses the current font-size
of the parent element as its base. It can essentially be used to scale up or scale down the font-size
of an element based on the font-size
inherited from the parent.
Let's say we have a parent div that has a font-size
of 16px
. If we create a paragraph element in that div
and give it a font-size
of 1em
the paragraph font-size
will be 16px
. However, if we give another paragraph the font-size
of 2em
that will translate to 32px
. Let's take a look at the example below.
A splash of HTML:
<div class="div-one">
<p class="one-em">1 em based on 10px</p>
<p class="two-em">2 em based on 10px</p>
</div>
<div class="div-two">
<p class="one-em">1 em based on 10px</p>
<p class="two-em">2 em based on 10px</p>
</div>
A drizzle of CSS:
*{
font-family: Arial, Helvetica, sans-serif;
}
.div-one {
font-size: 15px;
}
.div-two {
font-size: 20px;
}
.one-em {
font-size: 1em;
}
.two-em {
font-size: 2em;
}
And tada!
From the screenshot above we can see how EM can scale up the size of text and how they are affected by the current font-size inherited from their parent container.
You can test it out on codepen here: https://codepen.io/pedoch/pen/ZEoEZMe
Before you get all excited, I must warn you... it's not advisable to use EM especially within complex structured pages. If not used properly, we might run into scaling problems where elements might not be sized properly based on a complex inheritance of sizes in the DOM tree.
REM (Root EM)
Last but not least, REM. This works almost the same as EM, but the main difference is that REM only references the font-size
of the root element on the page rather than the parent's font-size
.
The root font-size
is the default font-size
specified either by the user in their browser settings or by you, the developer.
The default font-size
of a web browser is usually 16px
so therefore 1rem will be 16px
and 2rem
will be 32px
. However, in a case where the root font-size
is changed to 10px
for example; 1rem
will be 10px
and 2rem
will be 20px
.
Let's look at an example to make things a bit clearer.
A pinch of HTML:
<div class="div-one">
<!-- EM -->
<p class="one-em">1 em based on container (40px)</p>
<p class="two-em">2 em based on container (40px)</p>
<!-- REM -->
<p class="one-rem">1 rem based on root (16px)</p>
<p class="two-rem">2 rem based on root (16px)</p>
</div>
A smidgen of CSS:
html {
font-size: 16px;
}
* {
font-family: Arial, Helvetica, sans-serif;
}
.div-one {
font-size: 40px;
}
.one-em {
font-size: 1em;
}
.two-em {
font-size: 2em;
}
.one-rem {
font-size: 1rem;
}
.two-rem {
font-size: 2rem;
}
And boom!
As you can see, the paragraphs defined with REM units are completely undisturbed by the font-size
declared in our container and are strictly rendered relative to the root font-size
defined in the html
element selector.
You can test it out on codepen here: https://codepen.io/pedoch/pen/qBYEWjg
The Verdict:
Now that you understand how each unit works, I'll tell you which unit wins this fierce battle for me and why.
As mentioned earlier, I would not recommend you use EM due to the possibility of having a complex hierarchy of nested elements. This can cause problems because EM is relative to the font-size
it inherits from its parent, meaning text size can scale uncontrollably if not managed properly.
Bye bye EMππ½
Now PX and REM basically have the same effect on text; as we would get the same result if we used 32px
and 2rem
. This is because the default root font-size
is 16px
.
But REM has an advantage when accessibility comes into the picture.
When considering accessibility, we want users with limited vision to be able to read content on our websites comfortably. One way they can tweak the size of text on the screen is by using the browsers zoom
functionality.
The zoom functionality (shown above) works perfectly fine for both PX and REM. However, there's another way this can also be done. This is when the user changes the default font size from the browser's settings. This method allows the text on the user's screen to appear larger or smaller by default based on how they configure it. This frees the users from having to manually zoom every page they visit. Let's see how REM and PX perform with this method.
The first paragraph is set to font-size: 16px;
while the second is set to font-size: 1rem;
. As you can see, they are both the same size.
At the moment, my browser font size setting is on medium. Let's see what happens when I change it to very large.
The result:
As you can see the text set with REM was scaled appropriately with the new default/base font size we specified in the browser settings.
This to me is why I would definitely recommend using REM when working with text content on your web pages.
I think we have a winner!!! πππ
Note: REM does have its short comings when dealing with other use cases like padding. I will cover this in a different article.
If you made it this far, I want to say thank you very much.
I haven't written a lot of articles before and I know I have a lot more to learn so if you have contributions or think I didn't get something quite right, please leave a comment; as this will help me to continue to learn and grow.
Once again, thank you for your time and have a lovely day ππ½.
Top comments (15)
this was genuinely such a fun and insightful read! π thank you for this
Thank you for taking the time out to read it π
Yeah apparently rem/em should be avoided in spacing because then everything will scale proportionally to the font size which is the same as just zooming in/out.
rem won't scale to the font size unless the root font size (and therefore everything on the page) changes, in which case you should treat it as zooming in/out.
Yes, rem wouldn't scale unless the root font size changes
If I wanna male a responsive website, is 'rem' better in most cases? I'm looking forward to the next post(padding)!
They are all good with responsiveness as you can use media queries to define the font-sizes at different breakpoints. However, rem gets credit for the way accessibility is handled.
Thanks for the answer :)
It just depends on the use-case at the end π
That was one of the best discussions Iβve read on this subject. Thanks.
I'm happy you enjoyed it π
This was a nice Sunday read ππΎ
Thanks. I'm glad you enjoyed it π€²πΎ
Great write up, but you didn't cover when to use VW for font sizes.
And if you've never used VW for font sizes...well, you haven't lived yet...or gone crazy...
I had no idea veiwport units were used for typography. Defnitely trying this tonight π