Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

BEM rules in HTML and CSS

Class names are half of BEM. The other half is rules for the selectors themselves. They give the main benefit: the styles of any block can be read, changed and deleted without fear of affecting the rest of the page.

Classes only

In BEM CSS, selectors consist of classes. Tag selectors and ids are not used to style components:

Not allowedAllowedWhy
h3.card__titlethe <h3> tag is all over the page
#cart.cartan id is very strong, and there is only one per page
.card h3.card__titlethe heading becomes an <h2> — the style is gone

A class does not depend on the chosen tag. The card heading can become an <h2> or a <p> for semantics, and the look will not change. The exception is the site's base styles like the reset and body, covered in the lesson "Organizing CSS".

Flat specificity

Almost every selector is a single class. All rules have equal strength, so the lower one wins, and nothing needs to be "overridden":

<style>
  .note { padding: 8px 12px; border-left: 4px solid royalblue; background: aliceblue; }
  .note__text { margin: 0; }
  .note--warning { border-left-color: orange; background: oldlace; }
</style>
 
<div class="note"><p class="note__text">A regular note</p></div>
<div class="note note--warning"><p class="note__text">Attention: the warehouse is closed on Sunday</p></div>

The modifier comes after the block and wins, although the selectors have equal specificity. This is flat specificity.

Allowed exceptions

There are two cases where a two-part selector is justified. The first is pseudo-classes and states: .button:hover, .input:focus. The second is a block modifier that changes its elements:

<style>
  .card { padding: 12px; border: 1px solid silver; border-radius: 8px; max-width: 200px; margin-bottom: 8px; }
  .card__price { color: seagreen; font-weight: bold; }
  .card--sale .card__price { color: crimson; }
</style>
 
<div class="card">Backpack <span class="card__price">€40</span></div>
<div class="card card--sale">Tent <span class="card__price">€72</span></div>

One modifier on the block recolored the price inside, and there was no need to put a modifier on every element.

Files by blocks

In a large project each block's styles live in their own folder. Its images and script can be kept next to them:

blocks/
  button/
    button.css
  card/
    card.css
    card__price.css      (optional — a separate file for an element)
  header/
    header.css
styles.css               @import of all blocks one by one

Delete a block — delete the folder, and all its styles disappear with it. Dead CSS simply has nowhere to stay.

Common mistake

Styling tags inside a block instead of elements:

<style>
  .card { padding: 12px; border: 1px solid silver; border-radius: 8px; max-width: 240px; }
  .card p { margin: 0 0 8px; color: gray; }
  .notice { padding: 8px; background: gold; }
  .notice__text { margin: 0; color: black; font-weight: bold; }
</style>
 
<div class="card">
  <p>Product description</p>
  <div class="notice"><p class="notice__text">Only 2 left!</p></div>
</div>

The .card p rule hit the paragraph of the nested notice block: the text became gray even though it has its own class — .card p is stronger than a single class. Give the card paragraph its own card__text class, and the rule stops reaching into other blocks' tags.

Thanks for reading!

Donate to the site — we work hard for you.