The essential difference between em and rem is that rem is "root em". Now that out of the way let's first see what actually em is?
EM
EM is relative to the current font size of the parent element. This basically means that if the font size of the parent element is 16px then
1em == 16px
2em == 32px
3em == 48px
4em == 64px
and so on...
This is super cool because now you can use these relative units to size up almost everything perfectly!
And as a matter of fact, this unit also works on padding, margin, border, and whatnot. Padding, margins, borders, height, etc. directly relates to the font-size of the current element.
Look at the example below and the explanation even below.
<div class="main">
<div class="container">
<div class="em">
<h1>EM</h1>
<h3>This section explains EM</h3>
</div>
</div>
</div>
html {
font-size: 16px;
}
body {
font-size: 1em;
}
.container {
font-size: 2em;
}
.em {
font-size: 2em;
}
.em h1 {
font-size: 2.5em
}
.em h3 {
font-size: 0.5em;
}
.em>.block {
font-size: 0.5em;
border: 0.1em solid #000;
padding: 1em;
}
A caveat to em is that it supports compounding, which means if you have nested divs, each setting font-size based on em unit than the nested divs will compound the size starting from the root element to itself.
Here the font size of the "h1" tag would be:
16px * 1 * 2 * 2 * 2.5 = 160px;
And the font size of the "h3" tag would be
16px * 1 * 2 * 2 * 0.5 = 32px;
And the size of "1em" in ".block" div would be
16px * 1 * 2 * 2 * 0.5 = 32px;
Hence,
padding: 1em == padding: 32px;
border: 0.1em solid #000 == border: 3.2px solid #000
https://codepen.io/holdmypotion/pen/yLaZBbV
To fix up the compounding effect of em units(that quite frankly is a nuisance), rem was introduced(probably!)
REM
REM is relative to the font size of the root element. This solves the problem of compounding that occurs in the case of em. Whatever the font size of the parent element maybe, 1rem unit stays equal to the font size set in the HTML tag
html {
font-size: 32px;
}
/*Now 1rem == 32px */
Look at the example below:
<div class="main">
<div class="container">
<div class="rem">
<h1>REM</h1>
<h3>This section explains REM</h3>
</div>
</div>
</div>
html {
font-size: 32px;
}
body {
font-size: 1rem;
}
.container {
font-size: 2rem;
}
.rem {
/* Have no effect as we are setting the font size of h1 and h3
seperately using rem.
*/
font-size: 2rem;
}
.rem h1 {
font-size: 3rem
}
.rem h3 {
font-size: 1.2rem;
}
REM doesn't support compounding, which means all elements set their sizes based on the font-size of the root element
Here the font size of the "h1" tag would be:
16px * 3 = 48px;
And the font size of the "h3" tag would be:
16px * 1.2 = 19.2px;