Skip to content
⚠️ This article was written in 2018. Some content may be outdated.

CSS BEM 命名規則

プロジェクトが大きくなると、CSS の命名が混乱し始めます:.title.list-item.active……グローバルなスタイルの衝突が増えていきます。BEM 規則で命名を統一した後、問題が大幅に減りました。

BEM とは

BEM = Block(ブロック)、Element(エレメント)、Modifier(モディファイア)

Block(ブロック):独立したコンポーネント(header、menu、card など)
Element(エレメント):ブロックの構成要素。__ で接続(card__title、menu__item など)
Modifier(モディファイア):ブロックまたはエレメントの状態/バリアント。-- で接続(card--dark、menu__item--active など)

命名フォーマット

css
/* Block */
.card {
}

/* Element(card に属する子要素)*/
.card__title {
}
.card__content {
}
.card__footer {
}

/* Modifier(card のバリアント)*/
.card--dark {
}
.card--horizontal {
}

/* Element + Modifier */
.card__title--large {
}

実際の例

html
<!-- 商品カード -->
<div class="product-card product-card--featured">
  <img class="product-card__image" src="..." />
  <div class="product-card__body">
    <h3 class="product-card__title">商品名</h3>
    <p class="product-card__price">¥99</p>
    <p class="product-card__price product-card__price--original">¥199</p>
  </div>
  <div class="product-card__footer">
    <button class="product-card__btn product-card__btn--primary">
      カートに追加
    </button>
    <button class="product-card__btn product-card__btn--secondary">
      お気に入り
    </button>
  </div>
</div>
css
.product-card {
  border: 1px solid #eee;
  border-radius: 8px;
  overflow: hidden;
}

/* Modifier:特集商品 */
.product-card--featured {
  border-color: #f90;
  box-shadow: 0 2px 8px rgba(255, 153, 0, 0.3);
}

.product-card__image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.product-card__price {
  color: #f40;
  font-size: 18px;
  font-weight: bold;
}

/* 元値(取り消し線)*/
.product-card__price--original {
  color: #999;
  font-size: 14px;
  text-decoration: line-through;
}

SCSS で BEM を書く

scss
.product-card {
  border: 1px solid #eee;

  // &-- で Modifier を生成
  &--featured {
    border-color: #f90;
  }

  // &__ で Element を生成
  &__image {
    width: 100%;
  }

  &__price {
    color: #f40;

    // Element の Modifier
    &--original {
      color: #999;
      text-decoration: line-through;
    }
  }
}

BEM のメリット

1. 命名が自己説明的:クラス名を見ればその要素が何でどこに属するかわかる
2. 優先度が低い:クラスセレクターのみ使用。入れ子なし。スタイルの重みが一定
3. 再利用可能:Block は独立しており、どこにでも配置できる
4. 低結合:HTML 構造に依存しないため、リファクタリングが怖くない

BEM を使わない場面

- ユーティリティクラス(.text-center、.mt-16 など)は BEM 不要
- 状態クラス(.is-active、.has-error など)は is-/has- プレフィックスを使う慣習
- グローバルリセットスタイル

Vue の scoped との組み合わせ

vue
<style scoped>
/* scoped でスコープが分離されているため、BEM を適度に簡略化できる */
/* scoped がハッシュを付加するため、完全な block 名を書く必要はない */
.card {
  /* ... */
}
</style>

まとめ

  • BEM は CSS 命名の混乱を根本から解決する
  • Block・Element・Modifier の3層構造で、クラス名が自己説明的になる
  • SCSS の & 記法と組み合わせると書きやすい
  • Vue の scoped を使う場合は BEM を適度に簡略化できる

MIT Licensed