---
title: "Scaling CSS Components with BEM, REMs, & EMs"
url: "/articles/scaling-css-components-with-bem-rems-ems"
type: article
date: 2016-07-20
updated: 2021-01-12
---

# Scaling CSS Components with BEM, REMs, & EMs

#  Scaling CSS Components with BEM, REMs, &amp; EMs 

 How a little BEM and cleverness can make extensive use of EMs worth doing, and how it can up your game.

 By

 [  Wes Ruvalcaba   ](/about/wes-ruvalcaba) 

 July 20, 2016

  

Using relative units for measurements has a lot of advantages, but can cause a lot of heartache if inheritance goes wrong. But as Iâ&#128;&#153;ll demonstrate, BEM methodology and some clever standardization can reduce or eliminate the downsides.

## A little vocab before we get too far into this:

### `em` units

CSS length unit based on the font size of the current element. So if we set:

 ```css
.widget { font-size: 20px; }
```

For any style on that `.widget` element that uses em units, `1em = 20px`

### `rem` units

Similar to em units, except itâ&#128;&#153;s based on the â&#128;&#156;rootâ&#128;&#153;s emâ&#128;&#157;, more specifically the `<html>` tagâ&#128;&#153;s font-size. So if we set:

 ```css
html { font-size: 14px; }
```

Then **anywhere** in the page `1rem = 14px`, even if we used `rem` inside of our `.widget` elementâ&#128;&#153;s styles. Although `rem` can be changed, **`rem` should be left to it's default**. Majority of user's will have a default `font-size` of `16px`, so `1rem` will equal `16px`.

### Relative units

Any length thatâ&#128;&#153;s context based. This includes: `em` , `rem`, `vw` , `vh` and there are more. `%` isnâ&#128;&#153;t *technically* a unit, but for the purposes of this article, you can include them in the mix.

### `em` inheritance

This is `em`â&#128;&#152;s blessing and curse. Font size inherits by default, so any child of widget will also have a 20`px` font size unless we provide a style saying otherwise, so the size of an `em` will also inherit to the child.

Let's say we set `font-size` in `em` units, it can't inherit from itself, so for the `font-size` style an `em` is based on the parentâ&#128;&#153;s calculated `font-size.` Any other styleâ&#128;&#153;s em measurement will be based on the calculated `font-size` of that element.

When the page renders, all `em` units are calculated into a `px` value, browser inspector tools will have a "computed" tab for CSS that will give you calculated `px` values for any `em` based style.

Hereâ&#128;&#153;s an example thatâ&#128;&#153;s good for demonstration, but would create a ball of yarn if it was in your code.

If we have these three elements, each nested in the one before:

 ```css
.widget {
  font-size: 20px;
  margin-bottom: 1.5em; // 1.5em = 30px
}

.widget-child {
  font-size: 0.5em; // 0.5em = 10px
  margin-bottom: 1.5em; // 1.5em = 15px
}

.widget-grandchild {
  font-size: 1.4em; // 1.4em = 14px
  margin-bottom: 1.5em; // 1.5em = 21px
}
```

#### `line 3`

`em` will be calculated from the `font-size` of this element, `.widget`, which is `20px`  
  
`1.5em = 20px * 1.5 = ``30px`

#### `line 7`

Because this is a `font-size` style, it calculates `em` from the parentâ&#128;&#153;s `font-size`  
  
`.widget` has a calculated `font-size` of `20px`, so `1em = 20px `in this context.  
  
`0.5em = 20px * 0.5 = ``10px`

#### `line 8`

`em` will be calculated from the `font-size` of this element, `.widget-child`, which is `10px`  
  
`1.5em = 10px * 1.5 = ``15px`

#### `line 12`

Because this is a `font-size` style, it calculates `em` from the parentâ&#128;&#153;s `font-size`.   
  
`.widget-child` has a calculated `font-size` of `10px`, so `1em = 10px` in this context.  
  
`1.4em = 10px * 1.4 = ``14px`

#### `line 13`

`em` will be calculated from the `font-size` of this element, `.widget-grandchild`, which is `14px`.   
  
`1.5em = 14px * 1.5 = ``21px`

This is why most developers stay away from `em`â&#128;&#153;s, if done poorly it can get really hard to tell how `1em` will be calculated, especially because elements tend to have multiple selectors applying styles to them.

### `em` contamination

Unintended `em` inheritance that makes you angry.  

  

**All that said, there are two reasons I love `rem` and `em` units.**

## 1 â&#153;¡ Scalable Components

Weâ&#128;&#153;ve been creating fluid and responsive web sites for years now, but there are other ways our front-end code needs to be flexible.

Having implemented typography systems on large sites, I've found that specific â&#128;&#152;real worldâ&#128;&#153; implementations provoke a lot of exceptions to the style guide rules.

While this is frustrating from a code standardization standpoint, design is about the relationship of elements, and itâ&#128;&#153;s unlikely that every combination of components on every breakpoint will end up working as well as the designer wants. The designer might want to bump up the font size on an element in this template because its neighbor is getting too much visual dominance, a component may need to be scaled down on smaller screens for appropriate line lengths, or, on a special landing page, the designer may want to try something off script.

Iâ&#128;&#153;ve found this kind of issue to be much less painful when components have a base scale set on the component wrapper in `rem` units, and all other sizes in the component are set in `em` units. If a component, or part of a component, needs to be bumped up in a certain context, you can simply increase the font size of the component and everything inside will scale with it!

To show this in action, here are some article teasers to demonstrate `em` component scaling. Click on the CODEPEN image below and try modifying lines 1-15:  

  
*Note: For the rest of my examples Iâ&#128;&#153;m using a [class naming convention based on BEM and Atomic Design, also from my previous article](https://www.lullabot.com/articles/bem-atomic-design-a-css-architecture-worth-loving).*

[](https://codepen.io/wesruv/pen/KzeWYG/?editors=1100)

   

   

 ![Preview of scaleable teaser codepen](/sites/default/files/styles/wide_xs/public/assets/2016-07/codepen1.jpg.webp?itok=XaYw4byQ "codepen1.jpg")

To prevent unwanted em contamination, we're going to set a `rem` font-size on ***every*** component. Doing so, locks the scope of our em inheritance, and BEM gives us us an obvious place to do that.

 ![Visualization of a teaser list element](/sites/default/files/styles/max_900/public/assets/2016-07/dom-snippet_0.png.webp?itok=dUgxvFUT "dom-snippet.png")

For example, using the [teaser-list component from my previous article](https://www.lullabot.com/articles/bem-atomic-design-a-css-architecture-worth-loving) we want featured â&#128;&#152;teaser listsâ&#128;&#153; to be more dominant than a regular â&#128;&#152;teaser listâ&#128;&#153;:

 ```css
.o-teaser-list {
  font-size: 1rem;
}

.o-teaser-list--featured {
  font-size: 1.25rem;
}

.o-teaser-list__title {
  font-size: 1.25em; // In a normal context this will be 20px 
  // In a featured context this will be 25px
}
```

Meanwhile, in our teaser component:

 ```css
.m-teaser {
  font-size: 1rem;
}

.m-teaser__title {
  font-size: 1.125em; 
  // This will be 18px if it's a o-teaser-list or o-teaser-list--featured, 
  // because the component wrapper is using REM
}
```

Element scaling and adjustment becomes much easier, exceptions become less of a headache, and we accomplish these things without the risk of unintended `em` inheritance.

As a somewhat absurd example to demonstrate how powerful this can be, Iâ&#128;&#153;ve created a pixel perfect Lullabot logo out of a few `<div>` tags and CSS. A simple change to the font-size on the wrapper will scale the entire graphic (see lines 1â&#128;&#147;18 in the CSS pane):

[](https://codepen.io/wesruv/pen/aNKZGK?editors=1100)

   

   

 ![Preview of scaleable CSS art on codepen](/sites/default/files/styles/wide_xs/public/assets/2016-07/codepen2.jpg.webp?itok=VLnHt1RE "codepen2.jpg")

One potential drawback to this approach, it does take a little more brain-power to write your component CSS. Creating scaling components means your calculator app will be opened *a lot*, and youâ&#128;&#153;ll be doing a lot of this kind of computation:

 ```
$element-em = $intended-size-px / $parent-element-calculated-px
```

Sass (or similar preprocessor) functions can help you with that, and there are some tools that can auto-convert all `px` values to `rem` in your CSS for you since `rem` can be treated as a constant.

## 2 â&#153;¡ Works with Accessibility Features

The most common accessibility issue is low-vision, by a wide margin. For quite a while browser's zoom has worked *really well* with `px` units, I hung my hat on that fact and moved on using `px` everywhere in my CSS assuming that low vision users were taken care of by an awesome zoom implementation.

Unfortunately thatâ&#128;&#153;s not the case.

I attended an accessibility training by [Derek Featherstone](http://simplyaccessible.com/) who has done a lot of QA with users that depend on accessibility features. In his experience, low vision users often have applications, extensions or settings that increases the default font size *instead* of using the browserâ&#128;&#153;s zoom.

A big reason for this might be that in *most\** browsers zoom is site specific, while font size is a global setting.  *(\*Chrome is the only browsers I could find a global zoom setting.)*

Hereâ&#128;&#153;s how a low vision userâ&#128;&#153;s experience will breakdown depending on how font-sizes and breakpoints are defined:

### Scenario 1:

`font-size: px`  
  
`@media (px)`

The text size will be unaffected. The low vision user will be forced to try another accessibility feature so they can read the text, no good.

### Scenario 2:

`font-size: rem or em`  
  
`@media (px)`

The page can easily appear 'broken', since changes in font-size do not affect page layout.  
  
For example, a sidebar could have 6 words per line with default browser settings:

   

   

 ![Visualization of a sidebar with 'right sized', 6 words per line text](/sites/default/files/styles/wide_xs/public/assets/2016-07/just-right.png.webp?itok=4vi7mz-T "just-right.png")

But a user with a 200% font-size, the breakpoint will not change, so the sidebar will have 3 words per line, which will not look how we wanted, and often produces broken looking pages.

   

   

 ![Visualization of the layout being unchanged, but the type being twice as big, looking cramped](/sites/default/files/styles/wide_xs/public/assets/2016-07/too-big.png.webp?itok=LUwfU6pe "too-big.png")

### Scenario 3:

`font-size: rem or em`  
  
`@media (em)`

Users with an increased `font-size` default font size will get an (*almost\**) identical experience to users that use zoom. An increase in default font-size will proportionately effect the breakpoints, so in my opinion, [the EMs still have it](https://cloudfour.com/thinks/the-ems-have-it-proportional-media-queries-ftw/).

For example, if we have breakpoints in `em` a user with a viewport width of `1000px` that has their font-size at `200%` will get the same breakpoint styles as a user with a `500px` viewport and the default `font-size`.

\* The exception being media elements will definitely be resized with zoom, but may not change in size with an increased default `font-size`, unless their width is set with relative units.

**A quick note on em units in media queries:**  
  
Since media queries cannot be nested in a selector and don't have a 'parent element', `em` units will be calculated using the document's `font-size`.

Why not use `rem` you ask? It's buggy in *some* browsers *some* of the time, and even if it wasn't, it's one less character to type.

## Conclusion

For sites that donâ&#128;&#153;t have dedicated front-end people, or donâ&#128;&#153;t have complex components, this might be more work than itâ&#128;&#153;s worth. **At minimum** all of our font-size styles should be in `rem` units. If that sounds like a chore, [PostCSS has a plugin that will convert all px units to `rem`](https://github.com/cuth/postcss-pxtorem) (which can be used downstream of Sass/Less/Stylus). That will cover the flexibility and sturdiness needed for accessibility tools.

For large projects with ornate components, specific responsive scaling needs, and where one bit gone wrong can make something go from beautiful to broken, this can save your bacon. Itâ&#128;&#153;ll take some extra work, but keeping the `em` scope locked at the component level will keep extra work at a minimum with some pretty slick benefits.

 

   You must have JavaScript enabled to use this form.

## Get in touch with us

### Tell us about your project. We'd love to hear from you!

 First Name  

 Last Name  

 Your email address  

 Your organization  

 How you heard about us  

 Tell us more 

     Leave this field blank