【CSS】カオスを解消!BEMでスタイルを管理するコツ

R
R

BEMりませんか?

CSSでのスタイリングが複雑になってくると、要素同士が干渉しあったり、コードが増えるたびに管理が難しくなるという問題に直面することがよくあります。

クラス名が重複したり、スタイルの変更が別の場所に影響を及ぼすなど、デザインが崩れてしまう経験をしたことがあるかもしれません。

特に、プロジェクトが大規模になればなるほど、この「CSSのカオス」は避けられないものです。

そこで、そんなCSSの混乱を整理し、効率的に管理するために登場したのが「BEM(Block、Element、Modifier)」という命名規則です。

BEMは、CSSコーディングをコンポーネントベースで整理し、スタイルの管理を簡単にするためのシンプルかつ強力なツールです。

本記事では、BEMを使うことでどのようにCSSをすっきり整理し、読みやすく保守しやすいコードを書けるようになるのか、その基本とコツを紹介していきます。​

BEMの基礎

BEMとは何か?

BEM(Block、Element、Modifier)は、CSSの命名規則の一つで、コードを整理しやすく、保守性を高めるための方法です。

ロシアの検索エンジン「Yandex」で開発されたこの手法は、大規模なプロジェクトやチーム開発の現場で特に有効とされています。

BEMは3つのコンセプトに基づいています。

  1. Block(ブロック): ページ内で独立して存在する再利用可能なコンポーネントを指します。ボタンやナビゲーションバー、カードなど、UI要素の一つ一つがブロックに該当します。例: .button、.navbarなど。
  2. Element(エレメント): ブロック内に存在し、その一部を構成する要素です。エレメントは単独で存在することができず、ブロックに依存します。命名は「ブロック名__エレメント名」となります。例: .button__icon、.navbar__link。
  3. Modifier(モディファイア): ブロックやエレメントの見た目や振る舞いを変えるものです。モディファイアは、状態やバリエーションを表現します。命名は「ブロック名–モディファイア名」となります。例: .button–primary、.navbar__link–active。

この命名規則を使用することで、CSSクラス名が他の要素と衝突することなく、特定のブロックやエレメントのデザインを変更しやすくなります。

また、チーム内での協力や、プロジェクトが成長しても混乱しないようにコードを整理できます。

R
R

クラスの命名ルールを用いてCSSの管理や設計をしやすくしようというものです。


WebデザイナーがBEMを使用することのメリット、デメリット

メリット

1. 再利用性の向上

BEMの構造はコンポーネントベースであるため、特定のブロック(UIパーツ)やエレメントを他のページやプロジェクトでも簡単に再利用することができます。

これにより、開発時間を短縮し、メンテナンスが容易になります。

2. 可読性が高い

クラス名が「Block__Element–Modifier」という形式で明確に構造化されているため、どの部分がどの要素に対応しているかが一目で分かります。

特に、複数人が関わるチーム開発や、大規模なプロジェクトでは、クラス名の一貫性がコードの可読性を向上させます。

3. CSSの衝突を防ぐ

BEMを使うことで、スタイルのスコープがブロック単位で明確になり、クラス名の衝突が発生しにくくなります。

これにより、異なるページやセクションで同じクラス名を使うことで生じるスタイルの上書きなどの問題を回避できます。

4. 保守性が高い

コンポーネントが独立しているため、修正が必要なときに、影響範囲を限定的に抑えられます。

特定のブロックやエレメントにスタイルの変更があっても、他の部分に影響を与えないため、保守が容易です。

5. スケーラブル

プロジェクトが大規模になっても、BEMの命名規則を使うことで、新しい要素やページを追加してもコードの整理が保たれます。

プロジェクトが成長するにつれて、CSSのコードも拡張性が保たれ、混乱することなく運用できます。

デメリット

1. クラス名が長くなる

BEMでは「Block__Element–Modifier」という構造を守るため、クラス名がどうしても長くなりがちです。

たとえば、.product-card__image–largeといったクラス名は、短い命名規則に比べて冗長に感じることがあります。

R
R

自分の場合は慣れてしまえば、逆に見やすく感じるようになりました。

2. 習得コストがある

BEMを初めて使用する開発者にとっては、命名規則がやや複雑に感じられるかもしれません。

また、チーム全体でBEMを導入する場合、統一されたルールを遵守するために、学習コストやガイドラインの作成が必要です。

R
R

複数人での開発の場合、共通認識を作るまでは結構時間かかりました。

なんとなくあってるけど若干違う。。。的な部分を見直し、見直しで・・・

3. 規模の小さいプロジェクトでは過剰

小規模なプロジェクトや、簡単なページを作る場合には、BEMの命名規則はやや過剰であることがあります。

特に、特定のスタイルをすぐに適用できる場面では、シンプルなクラス名の方が効率的です。

R
R

広告用のLPなど、1ページものでグラフィックデザインの要素が強いページやコンポーネント化をする必要性が少ないページはBEMを使わずに組むことが多いです。

4. 設計段階の複雑さ

BEMはコンポーネントを明確に分けて設計することが求められますが、これにより初期段階でしっかりと設計しないと、後から手戻りが発生しやすくなるというリスクもあります。

R
R

実体験的には、最初はBEMを使うよりグチャグチャになりましたが、これも慣れれば使いやすいと思います。

BEMの命名ルールの基本

BEM(Block, Element, Modifier)は、CSSのクラス命名規則として非常に体系的で、特に大規模なプロジェクトやチームでの開発に役立つフレームワークです。

この命名規則は、コードの可読性と再利用性を向上させ、クラスの衝突を防ぎ、CSSの保守を容易にします。

ここでは、BEMの基本的な命名ルールを紹介します。

1. Block(ブロック)

Blockは、独立した再利用可能なUIコンポーネントを指します。ボタンやナビゲーションバー、カードなどが例です。

Blockは自己完結した要素であり、その中に他の要素(Element)が含まれることもあります。

Block名はその要素を説明する短い単語で命名します。

HTML
<div class="menu"></div>


上記の例では、menuがBlockです。

2. Element(エレメント)

ElementはBlockの一部を構成する要素で、Blockに従属する部分です。

エレメントは単独で存在せず、必ずBlockに属します。

クラス名はBlock名の後に、__(ダブルアンダースコア)で繋げます。

例:

HTML
<div class="menu">
  <div class="menu__item"></div>
  <div class="menu__link"></div>
</div>

ここで、menu__itemやmenu__linkがElementです。

3. Modifier(モディファイア)

ModifierはBlockやElementに対して外観や振る舞いを変更するために使われます。

たとえば、ボタンの色や大きさを変える場合にModifierを使います。

クラス名は、BlockまたはElement名の後に、–(ダブルハイフン)を追加して記述します。

例:

HTML
<div class="menu__item menu__item--active"></div>

この場合、menu__item–activeは、通常のmenu__itemに対して、状態を変更するModifierです。

BEM命名規則の構造

  • Block: block
  • Element: block__element
  • Modifier: block–modifier または block__element–modifier

BEM命名の基本例

HTML
<div class="card">
  <div class="card__header card__header--highlight"></div>
  <div class="card__body"></div>
  <div class="card__footer"></div>
</div>
  • cardはBlock
  • card__header, card__body, card__footerはElement
  • card__header–highlightはModifier

BEMの命名ルールを使うことで、CSSのコードが整理され、他の開発者ともスムーズにコラボレーションできる環境が整います。

また、命名規則が一貫しているため、大規模なプロジェクトでもスタイルの管理が簡単です。

このルールを理解し、実践することで、CSSの可読性やメンテナンス性を大きく向上させることができます。

このように、BEMを使うとクラス名が他と衝突しづらくなり、可読性が向上します。

BEMを使う上での留意事項

  • ブロック内に他のブロックはOK:ブロックは独立しているので、別のブロックを含めることができる。
  • エレメントの中にブロックは避ける:エレメントはブロックの一部として機能するので、エレメントの中にブロックを置くのは適切ではない。
R
R

ブロックの中にブロックをとか、ブロックであり、エレメントである要素ができてしまったりとかよくありました。(今でもあるかも・・・)
慣れるまでは完璧を求めずやってみることをおすすめします。


BEMを使った実装例

BEMの命名規則を使うことで、CSSのクラス名が明確に整理され、プロジェクトの規模が大きくなっても管理しやすいスタイルを維持できます。

以下に、具体的な実装例を紹介します。

1. シンプルなカードコンポーネント

HTML
<div class="card">
  <div class="card__header">
    <h2 class="card__title">Card Title</h2>
  </div>
  <div class="card__body">
    <p class="card__text">This is the card content.</p>
  </div>
  <div class="card__footer">
    <button class="card__button card__button--primary">Learn More</button>
  </div>
</div>

説明:

  • card はメインのブロックです。このカード全体を指しています。
  • card__header, card__body, card__footer はブロックに属するエレメントです。
  • card__button–primary はモディファイアで、スタイルの変化(この場合は主なボタンのスタイル)を指定しています。

2. ボタンのバリエーションをModifierで実装

BEMでは、Modifierを使って同じブロックやエレメントに異なるバリエーションを適用できます。

HTML
<button class="btn btn--large">Large Button</button>
<button class="btn btn--small">Small Button</button>
<button class="btn btn--primary">Primary Button</button>
<button class="btn btn--secondary">Secondary Button</button>

説明:

  • btn はボタンの基本ブロック。
  • btn–large, btn–small, btn–primary, btn–secondary はボタンに異なるサイズやスタイルを適用するモディファイア。

3. ナビゲーションメニューの例

HTML
<nav class="nav">
  <ul class="nav__list">
    <li class="nav__item nav__item--active">
      <a href="#" class="nav__link">Home</a>
    </li>
    <li class="nav__item">
      <a href="#" class="nav__link">About</a>
    </li>
    <li class="nav__item">
      <a href="#" class="nav__link">Contact</a>
    </li>
  </ul>
</nav>

説明:

  • nav はナビゲーション全体を表すブロック。
  • nav__list はリスト全体を指し、nav__item はそれぞれのリスト項目を表すエレメント。
  • nav__item–active はアクティブな状態を示すModifier。

4. フォームのデザイン例

HTML
<form class="form">
  <div class="form__group">
    <label for="email" class="form__label">Email</label>
    <input type="email" class="form__input" id="email" />
  </div>
  <div class="form__group">
    <label for="password" class="form__label">Password</label>
    <input type="password" class="form__input" id="password" />
  </div>
  <button class="form__button form__button--submit">Submit</button>
</form>

説明:

  • form は全体のブロックで、form__group は入力フィールドのグループ。
  • form__label と form__input はそれぞれラベルと入力フィールドを指すエレメント。
  • form__button–submit は送信ボタンに対するModifierで、送信ボタン特有のスタイルを指定します。

BEMの命名規則を使うことで、CSSのクラス名が明確に整理され、チーム開発でも効率よく作業が進められます。

特に、コンポーネントベースの設計を取り入れることで、メンテナンスがしやすくなり、プロジェクトの規模が大きくなってもスムーズに対応できるようになります。


BEMと普通のCSS命名との比較

BEM(Block, Element, Modifier)と従来のCSS命名方法を比較すると、コードの整理や保守性に大きな違いがあります。

BEMは、その構造化された命名規則を通じて、CSSを管理しやすくするために設計されており、特に大規模なプロジェクトやチームでの開発においてそのメリットが顕著です。

従来のCSS命名方法

従来のCSS命名方法では、セレクタを直接的にクラス名として付けることが一般的です。

例えば、ボタンのスタイルを表現する場合、以下のように記述されることがあります。

CSS
/* 従来のCSS命名 */
.button {
  background-color: blue;
  color: white;
}

.button-large {
  padding: 20px;
}

.button-small {
  padding: 10px;
}

この命名方法はシンプルで、少量のスタイルを書く場合には十分機能しますが、プロジェクトが大きくなると問題が生じます。

特にクラス名が増えるにつれて、どのクラスが何を意味しているのかが不明瞭になり、スタイルの重複や競合が発生しやすくなります。

R
R

この頃は変な名前ばかりつけていたなー。

BEMによるCSS命名

一方、BEMではクラス名がコンポーネントの構造に基づいて付けられ、要素の役割や修飾を明確に区別することができます。

たとえば、同じボタンのスタイルをBEMで記述すると、以下のようになります。

CSS
/* BEMの命名 */
.button {
  background-color: blue;
  color: white;
}

.button--large {
  padding: 20px;
}

.button--small {
  padding: 10px;
}

このように、BEMでは「ブロック(Block)」としてのbuttonを定義し、そのブロックに対する修飾(Modifier)を–largeや–smallとして表現します。

これにより、クラス名が一貫しており、コード全体の可読性が向上します。

また、修正や変更が必要になった場合にも、影響範囲が明確で、予期しない副作用を避けやすくなります。

比較のポイント

1.再利用性の向上

BEMは、コンポーネントごとに独立したクラス名を付けるため、スタイルの再利用がしやすくなります。

従来のCSSでは、同じ要素を異なる場所で使用するときに、クラスの重複や競合が発生しやすく、他のスタイルに影響を与えてしまうことが多々あります。

2.保守性の向上

従来のCSS命名では、長期的なプロジェクトやチームでの開発でスタイルの管理が困難になることがあります。

BEMは、コンポーネント単位でスタイルを分けるため、保守性が大幅に向上します。

3.予期せぬ副作用の防止

BEMの命名規則により、スタイルの変更が他の部分に影響を与えることを防ぐことができます。

従来のCSS命名では、グローバルなクラス名が原因で、同じ名前のクラスが他の要素に適用され、意図しないデザイン変更が起こるリスクがあります。

比較のポイントまとめ

BEMを使うことで、従来のCSS命名方法に比べて、コードが整理され、保守性が向上します。

また、プロジェクトが大きくなってもスタイルの競合を防ぎ、チームでの開発がしやすくなります。

初心者にとっては、最初は少し複雑に感じるかもしれませんが、長期的に見れば非常に効果的な方法です。

BEMを使いこなすためのベストプラクティス

BEM(Block, Element, Modifier)を効果的に活用するためには、いくつかのベストプラクティスを理解し、プロジェクトに適用することが重要です。

以下に、BEMを使いこなすためのベストプラクティスを紹介します。

1. コンポーネント単位で考える

BEMの基本は、要素を「コンポーネント」として考え、再利用可能なブロックとして設計することです。

各ブロックは、独立して動作し、再利用できるように設計されるべきです。

たとえば、ナビゲーションバー、カード、ボタンなどは、それぞれ独立したブロックと考えられ、別の場所でも同じスタイルで使用できるようにします。

HTML
<nav class="navbar">
  <ul class="navbar__list">
    <li class="navbar__item">Home</li>
    <li class="navbar__item">About</li>
  </ul>
</nav>

2. 一貫した命名ルールの適用

BEMでは命名規則が一貫していることが最も重要です。

プロジェクト全体で同じルールに従うことで、チームメンバー全員がどこにどのようなスタイルが適用されているか理解しやすくなります。

要素(Element)や修飾子(Modifier)の命名は、常に親ブロック名に依存しており、簡単に追跡できます。

CSS
.button {}
.button--primary {}
.button__icon {}

3. モディファイアを慎重に使う

モディファイアはブロックや要素のバリエーションを表すために使用しますが、これを多用しすぎると可読性が低下します。

修飾子は、そのコンポーネントの状態やバリエーションを明確に表現するために使い、シンプルでわかりやすい形で使用するよう心がけましょう。

CSS
.button--large {} /* 大きいボタン */
.button--disabled {} /* 無効なボタン */

4. ブロック同士の依存関係を避ける

各ブロックはできるだけ独立しており、他のブロックに依存しないように設計することが理想です。

これにより、特定のブロックが他のブロックの変更によって壊れることがなくなり、デザインの保守性が向上します。

HTML
<div class="card">
  <h3 class="card__title">Card Title</h3>
  <p class="card__text">This is a card text.</p>
</div>

5. モジュール化と再利用を意識する

BEMを使うことで、コードがモジュール化され、再利用がしやすくなります。

たとえば、カードコンポーネントを使い回すことで、同じスタイルを他のページやプロジェクトでも簡単に再利用できるようになります。

6. ネストを最小限に抑える

CSSのネストはコードを読みにくくし、将来のメンテナンス性を低下させます。BEMでは、ネストを最小限に抑え、シンプルでフラットな構造を心がけます。

これは、BEMの命名規則が一貫しているため、深いネストを避けてもスタイルの適用範囲がわかりやすいというメリットがあります。

BEMの拡張:他の命名規則やCSSアーキテクチャとの組み合わせ

R
R

まずはBEMを覚える感じでOK!ご参考までに!

BEMは、CSSをより整理しやすく、再利用可能なコードを書くための優れた命名規則ですが、他のCSSアーキテクチャや命名規則と組み合わせることで、さらに強力で柔軟なスタイル管理を実現することができます。

ここでは、BEMとよく組み合わせて使われる他のアプローチや命名規則、そしてそのメリットについて説明します。

1. OOCSS(Object-Oriented CSS)

OOCSSは、BEMと非常に相性が良いCSSアーキテクチャの一つです。

OOCSSでは、CSSを構造スキンに分けて管理し、再利用性とメンテナンス性を高めます。

BEMの命名規則を使うことで、OOCSSのコンセプトを簡単に実現できます。

たとえば、OOCSSでは「構造」をBlockやElementとして定義し、「スキン」をModifierとして扱うことで、見た目と機能を分離できます。

例:

CSS
/* OOCSSにおけるBEMの命名規則 */
.card {
  /* 構造 */
  display: flex;
  padding: 20px;
}
.card--dark {
  /* スキン */
  background-color: #333;
  color: #fff;
}

2. SMACSS(Scalable and Modular Architecture for CSS)

SMACSSは、スタイルをモジュール化して、スケーラブルなCSSアーキテクチャを構築する手法です。

SMACSSの中では、BaseLayoutModuleStateThemeといったカテゴリーにCSSを分類します。

BEMを組み合わせることで、各モジュールの命名やスタイル管理をさらに明確化でき、コードの一貫性が向上します。

例:

CSS
/* SMACSSにおけるBEMの例 */
.layout-header__logo {
  width: 150px;
}
.module-card__content {
  padding: 10px;
}
.state-is-active {
  border: 2px solid blue;
}

3. ITCSS(Inverted Triangle CSS)

ITCSSは、CSSファイルの構造をピラミッド型の階層にし、低レベルのスタイルから高レベルのコンポーネントへと段階的にスタイルを適用するアプローチです。

BEMと組み合わせることで、コンポーネント単位での管理がより明確になり、スタイルの重複や競合を防ぐことができます。

例:

CSS
/* ITCSSの階層に基づいたBEMの適用例 */
._utilities {
  /* ユーティリティクラス(低レベル) */
  margin: 0;
  padding: 0;
}
.component__button--primary {
  /* コンポーネントのスタイル(高レベル) */
  background-color: blue;
  color: white;
}

4. BEMとAtomic Design

Atomic Designは、UIをAtomMoleculeOrganismといった単位に分け、システムとしてデザインを管理する手法です。

BEMと組み合わせることで、各コンポーネントの役割がより明確になり、命名規則が一貫してわかりやすくなります。

たとえば、MoleculeをBlock、AtomをElementとして命名することが可能です。

例:

CSS
/* Atomic DesignとBEMの組み合わせ */
.atom-button__icon {
  margin-right: 10px;
}
.molecule-form__input {
  padding: 5px;
  border: 1px solid #ddd;
}

5. BEMの拡張命名規則

BEMはそのまま使うこともできますが、プロジェクトに応じて少し拡張して使うことも可能です。

たとえば、プロジェクト名やコンポーネント名をプレフィックスとして付けることで、さらなるモジュール化や名前の競合を防ぐことができます。

例:

CSS
/* プロジェクト名やコンポーネント名を追加した拡張BEM */
.app-card__title {
  font-size: 18px;
}
.site-header__nav {
  display: flex;
}


BEMは、他のCSSアーキテクチャや命名規則と組み合わせることで、CSSの管理やメンテナンス性がさらに向上します。

それぞれのアプローチには特有の利点があり、プロジェクトの規模や目的に応じて使い分けることで、柔軟で拡張性の高いCSSコーディングを実現できます。

まとめ

BEMは、CSSのカオスを整理し、プロジェクトのスケールやチーム開発の複雑さを解決するための強力な命名規則です。

BEMの原則に従うことで、クリーンで再利用可能なコードを記述でき、メンテナンス性が向上します。

また、他のCSSアーキテクチャや命名規則と組み合わせることで、さらに柔軟で拡張性の高いコーディングが可能になります。

BEMの使い方に慣れることで、特に大規模プロジェクトや長期運用において、その効果を最大限に発揮できるでしょう。

今後のプロジェクトでBEMを活用し、効率的かつ体系的にCSSを管理することで、デザインの一貫性とコーディングの効率が向上します。

次のステップとして、BEMの基本を理解したら、実際のプロジェクトで試してみることをお勧めします。

さらに、他の命名規則やアーキテクチャと組み合わせることで、あなたのプロジェクトに最適なスタイル管理方法を見つけましょう。​

R
R

BEMは使わなくても実際にはコーディングできてしまうと思いますが、デザインを再現するコーダーの次の一歩として上を目指していきましょう!