bem

BEM (Block Element Modifier) CSS naming convention. Enforces class name structure as block__element--modifier using double underscore for elements and double dash for modifiers. Activate when creating new components, writing CSS class names, adding HTML markup with class attributes, or reviewing existing BEM compliance. Covers naming rules, block vs element decisions, modifier usage, mixes, and external geometry positioning.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "bem" with this command: npx skills add yeeroen/skills/yeeroen-skills-bem

BEM — CSS Naming Convention

BEM is a component-based naming convention for CSS classes. Class names follow the pattern block__element--modifier. Blocks are standalone reusable components, elements are parts of a block that have no meaning outside it, and modifiers define appearance, state, or behavior variations.

Reference: https://en.bem.info/methodology/

Naming Rules

  • Names use lowercase Latin letters
  • Words within a name are separated by a single hyphen (-)
  • Element names are separated from the block name by double underscore (__)
  • Modifier names are separated from the block or element name by double dash (--)
  • Boolean modifiers have no value: block--disabled
  • Key-value modifiers use a hyphen between name and value: block--size-m
  • Elements always belong to a block, never to another element

Pattern:

block-name__element-name--modifier-name
block-name__element-name--modifier-name-value
block-name--modifier-name
block-name--modifier-name-value

Core Patterns

Naming a block and its elements

<form class="search-form">
  <input class="search-form__input">
  <button class="search-form__button">Search</button>
</form>
.search-form {}
.search-form__input {}
.search-form__button {}

The block name (search-form) describes purpose, not appearance. Elements are flat — all belong directly to the block regardless of DOM nesting depth.

Applying modifiers

A modifier class is always used together with the unmodified block or element class. The base class provides default styles; the modifier overrides specific properties.

<form class="search-form search-form--focused">
  <input class="search-form__input">
  <button class="search-form__button search-form__button--disabled">Search</button>
</form>
.search-form--focused {
  border-color: blue;
}

.search-form__button--disabled {
  opacity: 0.5;
  pointer-events: none;
}

Using mixes for external geometry

Blocks must not set their own external geometry (margin, position). Use a mix to apply positioning via the parent block's element class.

<header class="header">
  <form class="search-form header__search-form"></form>
</header>
/* search-form block: no margin or position rules */
.search-form {
  font-family: Arial, sans-serif;
}

/* Parent block controls positioning via its element */
.header__search-form {
  margin: 30px;
  position: relative;
}

Block vs element decision

Create a block when the section of code can be reused independently. Create an element when the section cannot be used separately from its parent block. If an element needs to be broken into sub-parts, create a new block instead of nesting elements.

Common Mistakes

CRITICAL Chaining elements creates deep, fragile class names

Wrong:

<form class="search-form">
  <div class="search-form__content">
    <input class="search-form__content__input">
    <button class="search-form__content__button">Search</button>
  </div>
</form>

Correct:

<form class="search-form">
  <div class="search-form__content">
    <input class="search-form__input">
    <button class="search-form__button">Search</button>
  </div>
</form>

Elements of elements (block__elem1__elem2) do not exist in BEM. The block name defines the namespace for all elements. Regardless of DOM nesting depth, every element's class name contains only block__element — never chained deeper. Chaining couples class names to DOM structure and breaks when elements are moved.

Source: https://en.bem.info/methodology/quick-start/#nesting-1

HIGH Using a modifier class without the base class

Wrong:

<form class="search-form--theme-islands">
  <input class="search-form__input">
  <button class="search-form__button">Search</button>
</form>

Correct:

<form class="search-form search-form--theme-islands">
  <input class="search-form__input">
  <button class="search-form__button">Search</button>
</form>

A modifier changes appearance, behavior, or state — it does not replace the entity. Without the base class, all default styles defined on .search-form are lost, causing broken or unstyled rendering.

Source: https://en.bem.info/methodology/quick-start/#a-modifier-cant-be-used-alone

HIGH Setting external geometry on the block itself

Wrong:

.search-form {
  font-family: Arial, sans-serif;
  margin: 30px;
  position: absolute;
  top: 0;
  right: 0;
}

Correct:

.search-form {
  font-family: Arial, sans-serif;
}

/* In the parent block's stylesheet */
.header__search-form {
  margin: 30px;
  position: absolute;
  top: 0;
  right: 0;
}

A block must not set its own margin or position. These properties couple the block to a specific context and prevent reuse. Use a mix to set external geometry via the parent block's element.

Source: https://en.bem.info/methodology/css/#external-geometry-and-positioning

HIGH Nesting BEM selectors creates unnecessary specificity

Wrong:

.search-form .search-form__input {
  color: red;
}

Correct:

.search-form__input {
  color: red;
}

BEM class names already encode the relationship between block and element, so descendant selectors are redundant. They raise specificity, making modifiers harder to override and coupling styles to DOM nesting order. Use flat single-class selectors.

Source: https://en.bem.info/methodology/css/#nested-selectors

MEDIUM Using tag or ID selectors instead of class selectors

Wrong:

#search-form {}
form.search-form {}
.header button {}

Correct:

.search-form {}
.search-form__button {}

BEM uses only class selectors. Tag selectors (.header button) create implicit dependencies on DOM structure. ID selectors are unique per page and prevent reuse. Combined tag+class selectors (form.search-form) raise specificity and cause override battles with modifiers.

Source: https://en.bem.info/methodology/css/#selectors

MEDIUM Naming blocks by appearance instead of purpose

Wrong:

<div class="red-text">Error: invalid input</div>

Correct:

<div class="error">Error: invalid input</div>

Block names describe what the component is ("error"), not what it looks like ("red-text"). Appearance-based names break when the design changes, requiring updates across HTML, CSS, and JavaScript.

Source: https://en.bem.info/methodology/quick-start/#block

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

linear-drafter

No summary provided by upstream source.

Repository SourceNeeds Review
General

OpenClaw Skill Growth

Make OpenClaw Skills observable, diagnosable, and safely improvable over time. Use this when the user wants to maintain many SKILL.md files, inspect repeated...

Registry SourceRecently Updated
General

Find Skills for ClawHub

Search for and discover OpenClaw skills from ClawHub (the official skill registry). Activate when user asks about finding skills, installing skills, or wants...

Registry SourceRecently Updated
2851Profile unavailable
General

Skill Listing Polisher

Improve a skill's public listing before publish. Use when tightening title, description, tags, changelog, and scan-friendly packaging so the listing looks cl...

Registry SourceRecently Updated
1130Profile unavailable