BEM and Sass
BEM names are long, and in CSS the block name has to be repeated many times. Many projects write styles in Sass — a preprocessor: a program that turns code in an extended language into ordinary CSS. Sass files have the .scss extension, and the browser receives a ready-made .css file.
Gluing names with &
In Sass the & symbol inside a rule means the parent selector, and a continuation of the name can be glued to it. This way a block, its elements and modifiers are written as one group:
.card {
padding: 12px;
border: 1px solid silver;
&__title {
margin: 0 0 4px;
}
&__price {
color: seagreen;
}
&--sale {
border-color: crimson;
}
}After processing you get ordinary single-class selectors:
.card { padding: 12px; border: 1px solid silver; }
.card__title { margin: 0 0 4px; }
.card__price { color: seagreen; }
.card--sale { border-color: crimson; }Specificity stayed flat — Sass only shortened the code.
Native nesting cannot do this
In the lesson "CSS nesting" you saw that & exists in plain CSS too. But there it refers to the whole selector, not to a piece of text: the browser cannot glue &__title into .card__title:
<style>
.card {
padding: 12px;
border: 1px solid silver;
&__title { color: crimson; }
}
</style>
<div class="card">
<h3 class="card__title">The heading stayed black</h3>
</div>The card has its border, but the &__title rule did not apply. That is why name gluing is used only in Sass and similar preprocessors.
A modifier that changes elements
The exception from the previous lesson — a block modifier affecting an element — is also short in Sass:
.card {
&__price {
color: seagreen;
}
&--sale &__price {
color: crimson;
}
}The result is .card--sale .card__price — exactly the two-class selector we wrote by hand.
Order inside a block file
It helps to keep one order: first the styles of the block itself, then its modifiers, then the elements with their modifiers. Then the right rule is found in seconds in any block file, and modifiers sit below the base styles and win over them.
Common mistake
Nesting elements the way they are nested in the markup:
.card {
.card__body {
.card__title {
color: rebeccapurple;
}
}
}Without & this produces the descendant selector .card .card__body .card__title — three classes instead of one. Such a rule is hard to override with a modifier, and all the benefit of BEM is lost. Write &__title at the first level inside the block.