Responsive Fonts in CSS
Tags: css, webdev, design, html
Published: 2021-06-29 14:34:31

CSS provides a wide range of units to choose from while developing web applications. 
Many properties such as padding, margin, font-size, width, height, etc., take _**length**_ as values followed by a unit.

A good developer should be able to decide how and when to use these units.

## What is this blog post about?
We will discuss some of the common units in CSS that are used with fonts, and also understand how to make font-sizes responsive.

> **Find the demo site for the examples explained in this post [here](https://common-css-font-units.netlify.app/)** 

## Prerequisites for this blog
This post assumes that you are familiar with the basics of HTML and CSS.

<hr />

## Font Units in CSS
* Generally, **px**, **rem**, **em**, and **%** are the most sought out units in CSS.
* Although there are many other units available in CSS, the above-mentioned are preferred for ***`font-size`***.
* Let's discuss these four units, and try to understand how and when they can be used.

### Pixel
* **px** is an absolute unit. That is, it defines fixed values that do not scale when screen/ device width changes.
* These are commonly used as it is easy to understand, and effortless to use.
* It corresponds to 1/96<sup>th</sup> of an inch, and usually, the default size of the text in a browser is _16 pixels_. 
* Let's use the image below to understand **px** better.
   ![Paragraph with font-size in pixels](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7gl9w6b5ts1nj9jyijw.png)
    ```css
     div.pixel p {
        font-size: 20px;
        width: 300px;
     }
    ```
  * The `<p>` has a `font-size: 20px`. Now look at this image below that shows the same paragraph in a device with smaller screen size.
     ![Paragraph with font-size in pixels in smaller viewport](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8bdslz4x8hbsff6cve4c.png)
  * Notice how the `font-size` remains `20px` even when the viewport size decreases. 

<br />
  * This is the issue with using pixels for any of the properties that takes a length. It is non-responsive, and does not scale according to the viewport size.

* Check out the pen for the above code here: {% codepen https://codepen.io/bhaaratii/pen/KKmPGqR default-tab=css,result%} 

### Rem
* **rem** in a relative unit. That is it scales as the viewport size changes.
* This unit is highly flexible and is recommended by developers.
* The `r` in rem stands for **root**. 
  * _1 rem unit is the font-size of the root element, i.e. **`<html>`**_.

<br />
* Let's understand **rem** with an example. Consider the code below.
    ```css
     div.rem p {
         font-size: 2rem; /* 2 * 16 = 32px */
     }
    ```
  * Check out the pen for the above example here: {% codepen https://codepen.io/bhaaratii/pen/eYWYBXX default-tab=css,result %}

<br />
  * If you do not override the default font-size of the root element, i.e. `<html>`, it will have a font-size of `16px`.
    * The font-size of `<p>`, in the above example, would be 2 times the size of the root element. That is: 2 * 16 = **`32px`**. 
    ![Computed font-size of paragraph with rem unit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v43e41kj74m679qj5ayw.png)


<br />
<br />

* Another example could be overriding the default `16px` of the root element.
    ```css
     html {
         font-size: 20px;
     }
     div.rem p {
         font-size: 0.5rem;  /* 0.5 * 20 = 10px */
     }
    ```
  * Check out the pen for the above example here: {% codepen https://codepen.io/bhaaratii/pen/oNWNOOQ default-tab=css,result %} 


<br />
* As stated above **rem** is highly responsive and is UX friendly.
* To check for responsiveness, try this out.
  1. Go to your `browser settings`
  1. Under `appearance`, select `Font size`
  1. Try changing the `Font size` of your browser, and look at the computed result for the tag who's unit length is defined using `rem`
     ![GIF demonstrating how to change font size of browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ss2sjo4kvostvq6j2za.gif)
  * You will see that the font-size becomes responsive, and changes according to the chosen font size of the browser.

> ***NOTE***: If you override the default font-size of root element, changing the font-size of the browser will have no effect on the font-size of the content defined. 
  * Font-size defined using **rem** will be relative to the manual value that overrides the default root font-size.

<br /><br />  

### Em
* **em** is very similar to **rem**, but the difference is that **em** is _relative to it's parent container_.
* Let's use the same paragraph example and follow the code below.
    ```css
     div.em {
         font-size: 15px;
     }
     div.em p {
         font-size: 2em; /* 2 * 15 = 30px */
     }
    ``` 
  * Check out the pen for the above example here: {% codepen https://codepen.io/bhaaratii/pen/mdmdgQY default-tab=css,result %}

<br /><br />
  
* Since `<div>` is the parent of the `<p>`, the font-size of the content within `<p>` would be twice that of font-size defined for `<div>`.` 
  * That is, 2 * 15 = `30px would be the font-size of `<p>`.
* The image below shows the results of the above code
  ![Paragraph with font-size defined using em](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3d37745hytpxmgzcinrv.png)


<br /><br />
* Now, consider the scenario with code below:
* This is the HTML code  
    ```html
     <div class="em">
        <ul>
           <li>1. Lorem</li>
           <ul>
               <li>1.1. Lorem</li>
               <ul>
                   <li>1.1.1. Lorem</li>
               </ul>
           </ul>
        </ul>
     </div>
    ```
* This is the CSS code  
    ```css
     div.em {
        font-size: 20px;
     }
     ul {
        font-size: 2rem;
     }
     ```
<br />

* Guess what would happen to the content within `<li>`. What would be the font-size?
  ![Nested li font size when defined using em](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbx7jpwfggst1s056bba.png)

* Unexpected right? 
* This is when **em** gets tricky and out of hand. 
  * _When you have multiple nested elements, you need to be careful with the lengths you assign._
  * Check out the pen for the above `<ul>` example here: {% codepen https://codepen.io/bhaaratii/pen/qBmBRNN default-tab=css,result %} 

<br /><br />

* To check for responsiveness, you can try changing the font-size of the browser (as shown above for **rem**).

> ***NOTE***: If you override the default font-size of root element, changing the font-size of the browser will have no effect on the font-size of the content defined. 
  * Font-size defined using **em** will be relative to the parent of that element. _If the parent is the root, then the font-size of the element will be relative to the overridden font-size of root_. 


* Another important thing to note if you use **em** is that, when you use it for properties like width or padding, the length is derived from the font-size of the element itself.
  * For e.g. say you have a `<p>` element within a `<div>`, and the font-size of `<div>` is 12px, `<p>` is `2em`.
  * And you declare padding for `<p>` as 2em. Then, the padding of`<p>` would be `48px` and NOT `24px`.
  * _This is because the other properties multiply the value of font-size of the element itself_. 
  * So keep this in mind when you use **em** as the unit for font-sizes.
  
## Percentage
* **%** is a relative unit, and is _relative to the font-size of the parent element_.
* Using a similar scenario like we did for **em**, let's assume we have a `<p>` within a `<div>`.
    ```css
     html {
        font-size: 20px;
     }
     div.percentage {
        font-size: 150%;
     }
     div.percentage p {
        font-size: 200%;
     }
    ```
  * Find the pen for the above code here: {% codepen https://codepen.io/bhaaratii/pen/QWvWRGv default-tab=css,result %}

<br /><br />

* Let's see what the font-size of `<p>` will be.
  * The font-size for `<p>` depends on `<div>`, and the font-size of the `<div>` depends on it's parent. (In this case: `<html>`)
  * Since the font-size for `<html>` is 20px, the font-size of `<div>` should be 1.5 * 20 = `30px`.
  * And the font-size of `<p>` would be 30 * 2 = `60px`.

* Look at the image below to see the results of the above code: 
   ![Paragraph defined using p](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chh102kbhk42ahzdcrsj.png)

<br /> <br />

* To check for responsiveness, you can try changing the font-size of the browser (as shown above for **rem**).

> * ***NOTE***: If you override the default font-size of root element, changing the font-size of the browser will have no effect on the font-size of the content defined. 
  * Font-size defined using **%** will be relative to the parent of that element. _If the parent is the root, then the font-size of the element will be relative to the overridden font-size of root_. 

<hr />

## CONCLUSION
We have seen four different units that can be used with fonts in CSS. 
As stated previously, there are many more units to explore and use. But the above explained ones are most commonly used by developers.

> **Find the demo site for the examples explained in this post [here](https://common-css-font-units.netlify.app/)** 


* A thumb of rule that you can follow is use **rem** everywhere for fonts. As it inherits from the root element it's easy to use, manage and compute the size of the element.
* Moreover, it does not get exponentially multiplied (unlike **em**) when you define font-size for nested elements.


* ***em can be used when you want the child element to inherit font-size and behave like the parent.*** Just beware of the inheritance.


* As for **%**, it is very similar to **em**. But the main difference is that **em** scales faster than **%**. 
  ![em and percentage](https://kyleschaeffer.com/assets/img/font-size-2.gif)
  * There will hardly be any difference between **em** and **%** when users set the browser text size to “medium”.
  * But as you can see in the picture above, when browser text-size is set to **smallest**, then **em** is hardly legible when compared to **%**.
  * And when browser size is set to **largest**, **em** is displayed much larger than **%**.

* Most people use **px** as well for font-size. But I do not recommend using it at all as it's not user friendly and not responsive. 


In general I would suggest,
> ***rem > percentage > em > px***

<hr />

## References
* [W3Schools CSS Units](https://www.w3schools.com/css/css_units.asp)
* [Udemy Modern HTML and CSS From the Beginning Course](https://www.udemy.com/course/modern-html-css-from-the-beginning/)
* [MDN Web Docs CSS values and units
](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units)
* [MDN Web Docs Font Sizes](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size)
* [Blog on CSS Font-Size by Kyle Schaeffer](https://kyleschaeffer.com/css-font-size-em-vs-px-vs-pt-vs-percent)

<hr />

Thank you for reading this blog post. 

I hope you were able to understand the common units for font-sizes in CSS, and I am sure this would be very helpful while developing responsive websites in the future!

Do give this post a like, pin or save it, and share it with your dev friends!