BEM Class Names Give Front-End CSS a Naming Contract That Ends Selector Fights
Teams get a naming contract that stops one person's .btn from silently overriding another's, at the price of longer class names and slightly heavier HTML. No framework or build step is required.
BEM splits front-end styling into three named roles. A block is a standalone reusable component, like .menu or .card. An element is a child part that only means something inside its block, written with a double underscore: .menu__item. A modifier captures a state or variant with a double hyphen: .button--disabled. The full formula is .block, .block__element, .block--modifier, and .block__element--modifier.
Because selectors stay single-class and flat, BEM removes the specificity battles that deep nesting creates. Class names double as documentation: card__button--primary reads as the primary button inside the card without a stylesheet lookup. The trade-offs are longer names, extra classes in the HTML, and overkill for very small projects. Yandex proposed the convention, and it has become the working contract for teams that need shared CSS rules.
BEM is a convention that only pays off when the whole team follows the same naming rules; the naming rules do the work a style guide would otherwise do.
Self-documenting class names carry structure and state directly in the markup, so a selector like card__button--primary replaces both a comment and a stylesheet lookup.
The modifier rule prevents a common failure: because a modifier must sit alongside its base class, it cannot silently replace the component's base styles.
BEM asks teams to pay an upfront verbosity cost in exchange for less time spent debugging inherited CSS later.