Validating BEM using regex

BEM (Block-Element-Modifier) is a naming pattern that helps you reason about your implementations. Any text that embeds a hierarchy or structure is a suitable candidate for BEM. For instance, it can be used to name your CSS components or even keys in your configuration files.

BEM consists of three elements that increase in specificity and precedence as you move to the right:

  • Block, the most general identifier
  • Element, identifier within a Block
  • Modifier, modifies a Block-Element

You can read more about the methodology here.

To validate that our code follows correct BEM naming we can use regex. Since regex is quite hard to visualize, especially as it increases in length, we can use an online tool regexper that draws diagrams of the regex.

The regex pattern for valid BEM is:

^((([a-z0-9]+(_[a-z0-9]+)?)+((--)([a-z0-9]+(-[a-z0-9]+)?)+)?)|(([a-z0-9]+(_[a-z0-9]+)?)+__([a-z0-9]+(_[a-z0-9]+)?)+((--)([a-z0-9]+(-[a-z0-9]+)?)+)?))$

Quite overwhelming! The next sections will feature a break down of the regex expression.

Building Blocks

Below are the regex patterns for the three identifiers:

Block

([a-z0-9]+(_[a-z0-9]+)?)+`

link

Element

__([a-z0-9]+(_[a-z0-9]+)?)$

link

Modifier

((--)([a-z0-9]+(-[a-z0-9]+)?)+)?$

link

Possible Combinations

And then we can combine the regex patterns to handle the various combinations:

Block

([a-z0-9]+(_[a-z0-9]+)?)+

link

Block and Block modifier

([a-z0-9]+(_[a-z0-9]+)?)+(--)([a-z0-9]+(-[a-z0-9]+)?)+

link

Block and optional Block modifier

([a-z0-9]+(_[a-z0-9]+)?)+((--)([a-z0-9]+(-[a-z0-9]+)?)+)?

link

Block and Element

([a-z0-9]+(_[a-z0-9]+)?)+__([a-z0-9]+(_[a-z0-9]+)?)+

link

Block and Element and Element modifier

([a-z0-9]+(_[a-z0-9]+)?)+__([a-z0-9]+(_[a-z0-9]+)?)+(--)([a-z0-9]+(-[a-z0-9]+)?)+

link

Block and Element and optional Element modifier

([a-z0-9]+(_[a-z0-9]+)?)+__([a-z0-9]+(_[a-z0-9]+)?)+((--)([a-z0-9]+(-[a-z0-9]+)?)+)?

link

Result

Finally we end up with combined regex pattern for BEM:

^((([a-z0-9]+(_[a-z0-9]+)?)+((--)([a-z0-9]+(-[a-z0-9]+)?)+)?)|(([a-z0-9]+(_[a-z0-9]+)?)+__([a-z0-9]+(_[a-z0-9]+)?)+((--)([a-z0-9]+(-[a-z0-9]+)?)+)?))$

I wouldn't advise anyone to use this as the performance is quite lacking!

dark/light theme