When I started digging into CSS, I found various units for font-size
. It was a bit confusing as to which one to use when, where and why. After investing some time, I found three units that I decided to use in my projects – px
, em
and rem
.
px
Pixels are the easiest measurement to use. But there is a catch. Let’s say we used pixels throughout our website and we managed the media queries too. What if a user changes the default font-size of browser (or device)? Your header’s font-size (say 20px) will remain 20 px. Hence user’s font preferences won’t be reflected. Which is not a good user experience. So, pixels may be good at spacing and layout but are not good fit for font-size. ems and rems are at rescue.
em
An em
is equal to the computed font-size of that element’s parent. For example, If there is a div
element defined with font-size: 16px
then for that div
and for its children 1em = 16px
.
If font-size is not defined explicitly, that element will inherit it from the parent element. The inheritance continues to take place this way amongst ancestors up until the root element. Default font-size of the root element is provided by browser.
Here is an example for em.
<div id="parent" class="parent">
Parent
<div id="outerChild" class="child">
Outer child
<div id="innerChild" class="child">
Inner child
</div>
</div>
</div>
.parent {
font-size: 20px;
}
.child {
font-size: 1.5em;
}
Here, you can see we gave font-size: 20px
to.parent
and font-size: 1.5em
to.child
. Computed font sizes of both .child
(#outerChild
and #innerChild
) are different. #outerChild
uses font-size from its parent .parent
. So, computed font-size of #outerChild
will be 1.5 * 20px = 30px. And #innerChild
uses font-size from its parent #outerChild
(which already has computed font-size of 30px). Hence the computed font-size of nested .child
will be 1.5 * 30px = 45px.
If you want to use em
for your units, you have to be careful with your layout. It is a good practice not to define font-size explicitly except root element while using em
in your project.
em
works great with layout like sidebar menu where you want submenu items to have smaller font-size gradually. Here is an example for that.
Result Skip Results Iframe
EDIT ON
<div class="menu">
<div class="menu-item">
Home
</div>
<div class="menu-item">
About
<div class="menu-item">
Projects
<div class="menu-item">Professional Projects</div>
<div class="menu-item">Hobby Projects</div>
</div>
<div class="menu-item">Portfolio</div>
</div>
<div class="menu-item">
Services
</div>
<div class="menu-item">
Contact
</div>
</div>
/* Parent */
.menu {
font-size: 25px;
}
/* Child */
.menu-item {
font-size: 0.9em;
padding-left: 12px;
}
rem
rem
values are relative to the root html
element, not to the parent element. That is, If font-size of the root element is 16px then 1 rem = 16px for all elements. If font-size is not explicitly defined in root element then 1rem will be equal to the default font-size provided by the browser (usually 16px).
When it comes to spacing and font-sizing, I prefer to use rem
. Since rem
uses root element’s font-size instead of its parent’s font-size.
Let’s assume, font-size: 10px
is set for the root element which makes 1rem = 10px everywhere in our webpage. Since 1px = 0.1rem, calculations are easy. But setting root font-size in pixels will have same problem as I mentioned in the px section.
A solution for this problem is percentage. Usually default font-size of the browser is 16px. Setting font-size: 100% will make 1rem = 16px. But it will make calculations a little difficult. A better way is to set font-size: 62.5%. Because 62.5% of 16px is 10px. Which makes 1rem = 10px.
Here is an example code in SCSS:
<div class="main">
<div class="app-header">Header</div>
<div class="app">
<div class="sidebar-menu">
<div>Menu item 1</div>
<div>Menu item 2</div>
<div>Menu item 3</div>
<div>Menu item 4</div>
</div>
<div class="content">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum dolores obcaecati quibusdam hic eos quod, praesentium consectetur reprehenderit facere iusto accusamus fugit quidem suscipit facilis voluptatem fuga maiores quo vel?
</div>
</div>
</div>
:root {
font-size: 62.5%;
body {
margin: 0;
// Body font size 16px
font-size: 1.6rem;
}
}
.main {
.app-header {
// Header font size 24px
font-size: 2.4rem;
// Header padding 8px
padding: 0.8rem;
background-color: lightblue;
text-align: center;
}
.app {
display: flex;
.sidebar-menu {
// Menu font-size 18px
font-size: 1.8rem;
// Menu padding 8px
padding: 0.8rem;
width: 20vw;
background-color: lightgreen;
}
.content {
// Content padding 8px
padding: 0.8rem;
background-color: pink;
width: 80vw;
}
}
}
article-wrap
ems and rems solved problems which I faced using pixels. I use rem
in spacing (margin, padding, etc.) and font sizing. And I use em
for layouts like menu.