BEM your CSS
BEM your CSS
- CSS selectors become expensive!
- What is BEM?
- Why using BEM?
- How to use BEM with Sass?
CSS selectors become expensive!
With expensive we mean in the sense of performance or overwriting:
- The more levels your selector has, the more time it takes to reach your element and can apply the style.
- The more levels your selector has, the more difficult it is to debug.
- The higher the specificity the selector is, the more difficult to overwrite and debug it is.
What does it mean?
CSS selectors become expensive!
1 level selector
Example
.this-one-class {
color: #ccc;
}
.grandfather.is-deaf .grandfather .son .grandchild {
color: #ccc;
}
VS
5 levels selector
Which one is the most expensive? And takes more time to find the element?
CSS selectors become expensive!
1 level selector
Example
Expensive selector!
Harder to read and maintain
.this-one-class {
color: #ccc;
}
.grandfather.is-deaf .grandfather .son .grandchild {
color: #ccc;
}
VS
5 levels selector
CSS selectors become expensive!
1 level selector
Example
#section {
color: #ccc;
}
.grandfather .grandchild {
color: #ccc;
}
VS
2 levels selector
Which one is the most expensive? And takes more time to find the element?
CSS selectors become expensive!
1 level selector
Example
#section {
color: #ccc;
}
.grandfather .grandchild {
color: #ccc;
}
VS
2 levels selector
#ID selectors makes it expensive for debugging or overwriting.
More lightweight, easier to debug, easier to maintain
CSS selectors become expensive!
1 level selector
Example
.home-section {
color: #ccc;
}
nav.navigation ul.grandchild li a {
color: #ccc;
}
VS
6 levels selector
Which one is the most expensive? And takes more time to find the element?
CSS selectors become expensive!
1 level selector
Example
.home-section {
color: #ccc;
}
nav.navigation ul.grandchild li a {
color: #ccc;
}
VS
2 levels selector
Gives context, easy to overwrite or maintain
Selectors with elements and classes are very expensive. If elements are not in html, style does not apply
CSS selectors become expensive!
Browsers vs Humans
How a human read your selector:
nav ul li a
a li ul nav
How a browser read your selector:
CSS selectors become expensive!
Where browsers start
<nav>
<ul>
<li>
<a href="#">Link</a>
</li>
</ul>
</nav>
nav
ul
li
a
4.
3.
2.
1.
A browser start with the latest character and ends with the first
What is BEM
BEM stands for
Block, Element, Modifier
- ...an CSS naming convention
- ...an helper for you CSS classes
- ...a way of structure your CSS classes
BEM is....
What is BEM
.btn {}
<a href="#" class="btn">Button</a>
CSS
HTML
.navigation {}
<nav class="navigation"></nav>
.footer {}
<footer class="footer"></footer>
Block component
Block components are removable in one piece and are for a spexific purpose or use.
What is BEM
Element
.btn__icon {
font-size: 1em;
color: #000000;
}
<a href="#" class="btn">
<i class="btn__icon"></i>
</a>
CSS
HTML
.navigation__list {}
.navigation__list-item {}
.navigation__link {}
<nav class="navigation">
<ul class="navitgation__list">
<li class="navigation__list-item">
<a href="#" class="navigation__link">
</li>
</ul>
</nav>
Element that depends
What is BEM
.btn__icon {
font-size: 1em;
}
.btn__icon--small {
font-size: 0.5em
}
<a href="#" class="btn">
<i class="btn__icon--small"></i>
</a>
CSS
HTML
.navigation__link--active {
background-color: red;
}
<nav class="navigation">
<ul class="navitgation__list">
<li class="navigation__list-item--active">
<a href="#" class="navigation__link">
</li>
</ul>
</nav>
Modifier
The modifier changes the style of a block or element. Separated from the block with "--"
What is BEM
.navigation__link--transparant {
background: transparant;
}
Block (context)
Element
Modifier
This is BEM
Why use BEM
.nav ul {
margin: 0;
padding: 0;
list-style: none;
}
.nav ul ul {
padding-left: 1em;
}
.nav ul li {
float: left;
}
.nav ul li a {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.nav ul li ul li a {
background: #000000;
color: #cccccc;
}
<nav class="nav">
<ul>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li>
<a href="#">link</a>
<ul>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</li>
</ul>
</nav>
When you start with CSS
When you start with writing CSS, you get used to nesting to give context. This was very bad for maintainability and readability.
Why use BEM
.nav .list,
.nav .subnav {
margin: 0;
padding: 0;
list-style: none;
}
.nav .list .subnav {
padding-left: 1em;
}
.nav .list .item {
float: left;
}
.nav .list .item a {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.nav .list .subnav .item a {
background: #000000;
color: #cccccc;
}
<nav class="nav">
<ul class="list">
<li class="item"><a href="#">link</a></li>
<li class="item"><a href="#">link</a></li>
<li class="item"><a href="#">link</a></li>
<li class="item">
<a href="#">link</a>
<ul class="subnav">
<li class="item"><a href="#">link</a></li>
<li class="item"><a href="#">link</a></li>
</ul>
</li>
</ul>
</nav>
Then your getting better
Then you become better. You start with giving more elements classes for readability and maintainability.
Why use BEM
.list--reset {
margin: 0;
padding: 0;
list-style: none;
}
.navigation__sub-list {
padding-left: 1em;
}
.navigation__item {
float: left;
}
.navigation__link {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.navigation__sub-list .navigation__link {
background: #000000;
color: #cccccc;
}
<nav class="navigation">
<ul class="navigation__list list--reset">
<li class="navigation__item"><a href="#" class="navigation__link">link</a></li>
<li class="navigation__item"><a href="#" class="navigation__link">link</a></li>
<li class="navigation__item"><a href="#" class="navigation__link">link</a></li>
<li class="navigation__item">
<a href="#" class="navigation__link">link</a>
<ul class="navigation__sub-list list--reset">
<li class="navigation__item"><a href="#" class="navigation__link">link</a></li>
<li class="navigation__item"><a href="#" class="navigation__link">link</a></li>
</ul>
</li>
</ul>
</nav>
And there was BEM!
Someone tells you to checkout BEM, your gonna love it! It is gonna give readability, structure and maintainability.
Why use BEM
.list--reset {
margin: 0;
padding: 0;
list-style: none;
}
.navigation__sub-list {
padding-left: 1em;
}
.navigation__item {
float: left;
}
.navigation__link {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.navigation__sub-list .navigation__link {
background: #000000;
color: #cccccc;
}
Before & After
.nav ul {
margin: 0;
padding: 0;
list-style: none;
}
.nav ul ul {
padding-left: 1em;
}
.nav ul li {
float: left;
}
.nav ul li a {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.nav ul li ul li a {
background: #000000;
color: #cccccc;
}
What are the differences?
Why use BEM
.list--reset {
margin: 0;
padding: 0;
list-style: none;
}
.navigation__sub-list {
padding-left: 1em;
}
.navigation__item {
float: left;
}
.navigation__link {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.navigation__sub-list .navigation__link {
background: #000000;
color: #cccccc;
}
Before & After differences
- Most selectors became single class selectors
- A class has his own context
- More readable
- More maintainable
.nav ul {
margin: 0;
padding: 0;
list-style: none;
}
.nav ul ul {
padding-left: 1em;
}
.nav ul li {
float: left;
}
.nav ul li a {
font-weight: 600;
color: #000000;
background: #ccc;
display: inline-block;
padding: 0.5em;
}
.nav ul li ul li a {
background: #000000;
color: #cccccc;
}
Why use BEM
BEM benefits
1. Helps to write self defining context class selectors.
2. A class is most of the time not depended on the parent element or class.
3. Non-developers can read the code and tell where it is about!
How to use BEM with Sass
Example:
// Block
$module: 'navigation';
.#{$module} {
// Element
&__item {
border-top: 1px solid #ccc;
}
// Modifier
&--sub {
margin-left: 15px;
.#{$module}__link {
font-style: italic;
}
}
}
.navigation__item {
border-top: 1px solid #ccc;
}
.navigation--sub {
margin-left: 15px;
}
.navigation--sub .navigation__link {
font-style: italic;
}
Sources
- CSS performance revisited: selectors, bloat and expensive styles by Ben Frain
- BEM 101 by CSS-tricks
- MindBEMding - Getting your head 'round BEM syntax by CSSwizardry
BEM your CSS
By Raymon Schouwenaar
BEM your CSS
- 2,931