The Battle of the Units: PX vs REM vs EM (font-size)
Tags: webdev, html, css
Published: 2022-09-11 17:33:36

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](https://www.scientiamobile.com/what-is-pixel-density/#:~:text=Pixel%20density%20is%20a%20calculation,in%20the%20past%20several%20years.)_. 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.


![Barney Rubble looking confused](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xnutjculi3foidyiah77.gif)

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](https://www.youtube.com/watch?v=u0rfDeaxehc) or [this article](https://www.w3.org/Style/Examples/007/units.en.html#:~:text=The%20px%20unit%20is%20the%20magic%20unit%20of%20CSS.%20It%20is%20not%20related%20to%20the%20current%20font%20and%20usually%20not%20related%20to%20physical%20centimeters%20or%20inches%20either.) for a more in-depth explanation.

_Moving on..._

Let's look at an example below.

_A **dash** of HTML:_

```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:_

```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!**_


![Image showing text displayed in different screen sizes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/173zvkn2pdfcbxmpevq8.png)

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](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:_
```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:_

```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!**_


![Image showing how EM unit works](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fen4d12fbnsvro005ugl.png)

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](https://codepen.io/pedoch/pen/ZEoEZMe)_

![Meme saying, "Wait, wait, wait"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/th0vwzhcaebtyz0dv45l.gif)

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:_

```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:_

```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!**_

![Image showing how REM unit works compared to EM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sb3j1z8e4m1r27py4fsm.png)

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](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👋🏽_

![woman saying "bye bye"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34gpsygco39r3qm5t5nf.gif)

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.

![GIFS showing browser zoom functionality](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8rc9g9jn9em6dig3by8.gif)

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.

![texts saying "This paragraph is 16px" and "This paragraph is 1rem" styled with 16px and 1rem respectfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i46mymresa72taji7n3u.png)

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.

![GIF showing me change browser font size settings from medium to large](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cb2s0rhzplqmk9ccb76d.gif)

_The result:_

![texts saying "This paragraph is 16px" and "This paragraph is 1rem" styled with 16px and 1rem respectfully. But this time the text with REM is slightly bigger because the browser font size setting was changed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/olf7l4zihg7kl4qbgv59.png)

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!!! 🎉🎉🎉

![Girl standing, holding a trophy with confetti rain down on her](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dq4bqek14lt3pu9pf43r.gif)

_**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 👋🏽.