Blogs
Bem CSS

BEM

BEM, or Block-Element-Modifier, is a widely adopted naming convention for CSS class names. It is incredibly helpful for creating CSS that is more readable, maintainable, and scalable.

It’s been a convention I’ve adapted for years, and it has made my life easier and the rest of the team.

A BEM class name can consist of up to three parts:

  • Block: Represents the main parent element of the component.
  • Element: Refers to any child elements within the block.
  • Modifier: Indicates a variation of either a block or an element.

When all three are combined, a BEM class name might look like this:

1
block__element--modifier

Button Example

Block

The main component or container is the Block. In this case, the button class is the Block. It represents the outer structure or primary entity of the component.

Element

Elements are parts of the Block, and their class names are defined using a double underscore (__) followed by the element name. Here, there are three elements within the button Block:

  • button__prepend: Represents the leading icon part of the button.
  • button__body: Represents the main text content of the button.
  • button__append: Represents the trailing icon part of the button.
Modifier

Modifiers are not used in this specific example, but they can be added to represent different states or variations of a Block or Element. They are defined with a double hyphen (--) followed by the modifier name (e.g., button--large or button__body--highlighted).

button.component.tsx
1
import React from 'react';
2
3
const Button = () => {
4
return (
5
<a href="#" className="button">
6
<span className="button__prepend">...</span>
7
<span className="button__body">My Button</span>
8
<span className="button__append">...</span>
9
</a>
10
);
11
};
12
13
export default MyButton;

Photo Example

Here is another example:

photo.component.tsx
1
import React from 'react';
2
3
const Photo = ({ src, quote }: PhotoProps) => {
4
return (
5
<figure className="photo">
6
<img className="photo__img" src={src} alt="A picture of me" />
7
<figcaption className="photo__caption photo__caption--large">
8
{quote}
9
</figcaption>
10
</figure>
11
);
12
};
13
14
export default Photo;

Your CSS may look something like this:

photo.styles.scss
1
.photo { }
2
3
.photo__img { }
4
5
.photo__caption { }
6
7
.photo__caption--large {
8
font-size: 1.5rem;
9
}

or using nesting (my fav):

  • I do want to point out that this convention is not ideal if you’re using BEM, this is just for demonstrating purposes. When I’m not using BEM I’d like use the nesting feature A LOT, though, haha.
1
.photo {
2
// Base styles for the figure
3
padding: calc(var(--base-padding) * 2);
4
text-align: center;
5
6
&__img {
7
width: 100%;
8
height: auto;
9
border-radius: 10%;
10
}
11
12
&__caption {
13
margin-top: 10px;
14
15
&--large {
16
font-size: 1.5em; // Larger font size
17
}
18
}
19
}

Now, that you’ve seen some code, I want to talk about several addtional benefits that I often see:

No need for Universal Selector (*)

The universal selector signifies that the project includes a style that applies to all elements in the layout, which restricts the layout’s reuse in other projects.

A universal selector can make the project code unpredictable. For example, it can affect the styles of the universal library components.

No need for Combined Selectors

Combined selectors have greater specificity than single selectors, making it harder to override block styles.

Say you have some code like this:

html
1
<button class="button button_theme_blue button_active">...</button>

The .button_active selector does not override the properties defined in .button.button_theme_blue, as the latter is more specific. To redefine those properties, you should combine the block modifier selector with the .button selector and place it after .button.button_theme_blue, since both selectors have the same specificity.

scss
1
.button.button_theme_blue { }
2
.button.button_active { }

Using simple class selectors will prevent issues when it comes to redefining styles.

scss
1
.button_theme_blue { }
2
.button_active { }
3
.button { }