Suggest an editImprove this articleRefine the answer for “What is BEM methodology (block element modifier)”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**BEM (Block Element Modifier)** - a CSS class naming convention where classes follow a `block__element--modifier` pattern. ```css .card { } /* Block - standalone component */ .card__title { } /* Element - only exists inside .card */ .card--featured { } /* Block modifier - a variant */ .card__title--large { } /* Element modifier */ ``` **Key point:** `.card__title--large` can never conflict with `.nav__title--large`. The name itself is the scope.Shown above the full answer for quick recall.Answer (EN)Image**BEM (Block Element Modifier)** - a CSS class naming convention where every class follows a `block__element--modifier` pattern to prevent style collisions across a codebase. ## Theory ### TL;DR - Block = standalone UI piece (`button`). Element = part that only lives inside that block (`button__icon`). Modifier = a variation or state (`button--primary`). - Think LEGO: block is the base piece, element attaches only to that piece, modifier swaps its look. - Main win: `.menu__item--active` stays scoped to menus and never clashes with `.button--active`. - Use BEM on teams with 5+ devs or CSS over 10k lines. Skip it for tiny prototypes or CSS-in-JS projects. ### Quick example ```html <button class="button button--primary"> <span class="button__icon">★</span> Click me </button> ``` ```css .button { padding: 10px; border: 1px solid; } /* Block */ .button__icon { display: inline-block; margin-right: 5px; } /* Element */ .button--primary { background: blue; color: white; } /* Block modifier */ .button__icon--large { font-size: 20px; } /* Element modifier */ ``` The class name tells you the full relationship. `button__icon--large` is a large icon inside a button. Nothing else, nothing more. ### Key difference A flat class like `.active` is global. Merge three feature branches and you get three different `.active` rules fighting each other. That is the most common CSS conflict I have seen in team codebases. BEM namespaces everything: `.card--active`, `.menu__item--active`, `.button--active` are three separate selectors that cannot touch each other. ### When to use - Teams with 5+ developers or CSS over 10k lines: BEM naming prevents merge conflicts and unintended overwrites. - **Reusable component libraries**: elements tie to their block, so there is no semantic drift over time. - Vanilla CSS without build tools: BEM gives you scoping without PostCSS or Webpack. - CSS-in-JS (Styled Components, Emotion): skip BEM, the library hashes class names automatically. - **Tailwind CSS**: skip BEM, utility classes replace naming conventions entirely. - Small solo project under 5 files: flat classes are faster to write and BEM overhead is not worth it. ### Comparison | Aspect | BEM | Flat CSS (`.btn.active`) | CSS Modules | |---|---|---| ---| | Naming | `block__element--mod` | `.class`, `.state` | `Button_module__root` | | Scalability | High (namespaced) | Low (global collisions) | High (hashed at build time) | | Team size | 5+ devs | Solo or small | Any size | | Debugging | DevTools shows hierarchy | Hunt globals | Safe but obfuscated names | | Best for | Vanilla or team CSS | Prototypes | React/Vue components | ### How browsers handle BEM No runtime magic. Browsers parse BEM classes as standard CSS selectors. `.button__element` has specificity (0,1,0), same weight as any single class. That's it. Structure lives in the name, not in nesting or shadow DOM. Write flat selectors in CSS, never `.button .button__icon {}`. ### Common mistakes **Nesting selectors in CSS:** ```css /* Wrong - fails without PostCSS, breaks BEM intent */ .button { .icon { color: red; } } /* Right - always flat */ .button__icon { color: red; } ``` **Chaining too many modifiers on one class:** ```css /* Wrong - hard to read, hard to override */ .button--primary--large--rounded { } /* Right - separate modifier classes, combine in HTML */ .button--primary.button--large { } ``` **Deep element nesting:** ```css /* Wrong - BEM elements go only one level deep */ .header__nav__link { } /* Right - treat link as an element of nav */ .nav__link { } ``` **Expecting a block modifier to suppress an element modifier:** ```css .card { transition: opacity 0.3s; } .card--loading { opacity: 0.5; } /* Affects the block */ .card__spinner--fast { animation: spin 1s infinite; display: block; } /* Reality: --fast spinner still runs when .card--loading is present. * Block and element modifiers are independent selectors. * To hide the spinner during loading, write it explicitly: * .card--loading .card__spinner { display: none; } */ ``` ### Real-world usage - **Yandex** (where BEM was created) applies it in codebases over 1 million lines: `search__input--focused`. - **BBC News** uses it for modular templates: `article__headline--breaking`. - **Shopify themes** follow BEM naming: `product-form__input--error`. - **Google AMP** uses it consistently: `amp-form__submit-button--disabled`. ### Follow-up questions **Q:** Explain block, element, and modifier with an e-commerce example. **A:** Block is `cart`. Element is `cart__item` (one row in the cart). Modifier is `cart__item--out-of-stock` (strikethrough price, greyed out). The cart can appear anywhere on the page. The item only makes sense inside the cart. **Q:** How does BEM specificity compare to plain classes? **A:** `.block__element` has specificity (0,1,0), same as `.element`. BEM itself does not boost selector weight. Protection comes from the unique name. No `!important` needed. **Q:** Would you use BEM in a React project that already uses CSS Modules? **A:** Probably not. CSS Modules hash class names at build time, so `.button` in one file never collides with `.button` in another. Adding BEM on top would add verbosity without solving a problem Modules already handles. **Q:** (Senior) If a block has a modifier and one of its elements also has a modifier, does one affect the other? **A:** No. `.card--loading` changes the block. `.card__spinner--fast` changes the element. They are independent selectors and the browser applies both. If you want the spinner hidden while loading, add an explicit rule: `.card--loading .card__spinner { display: none; }`. ## Examples ### Basic button component ```html <button class="button button--primary"> <span class="button__icon">★</span> Submit </button> <button class="button button--secondary"> Cancel </button> ``` ```css .button { padding: 10px 20px; border: 1px solid transparent; cursor: pointer; } .button__icon { display: inline-block; margin-right: 6px; } .button--primary { background: #0057ff; color: #fff; } .button--secondary { background: #e0e0e0; color: #333; } ``` Two buttons, one block, two modifiers. Neither style leaks outside `.button`. ### E-commerce product card ```html <article class="product-card product-card--featured"> <img class="product-card__image" src="shirt.jpg" alt="T-shirt"> <h3 class="product-card__title">Cotton Tee</h3> <div class="product-card__price product-card__price--sale">$19.99</div> <button class="product-card__button product-card__button--add">Add to cart</button> </article> ``` ```css .product-card { display: flex; flex-direction: column; max-width: 300px; } .product-card__image { width: 100%; height: 200px; object-fit: cover; } .product-card__title { font-size: 1.2em; margin: 10px 0; } .product-card__price { font-weight: bold; color: green; } .product-card__price--sale { color: red; text-decoration: line-through; } .product-card__button { padding: 10px; background: #007bff; color: #fff; border: none; } .product-card__button--add:hover { background: #0056b3; } ``` `--featured` on the block lets you add a border or badge without touching any element styles. `--sale` on `__price` turns the price red with a strikethrough. No selector here needs more specificity than a single class.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.