【2023年】これからブログを始める人へおすすめの書籍

Kissy

CSS設計規則「BEM」のまとめ

作成: 更新:

BEM

この記事ではCSSの設計規則であるBEMについて記載します。

BEMとは?

CSSの設計規則でBlockElementModifierの3つの要素で設計していく手法です。

CSSのクラス名は特にルールを設けずに実装していると、いつか設計が破綻し、修正すると想定していない箇所に影響を及ぼすことになりかねません。一人で実装している場合は、すべて自分が把握しているので問題ないですが、複数人で実装する場合は破綻します。

そこで、BEMではBlockElementModifierの3つの要素に分けて設計していきます。3つの要素はそれぞれ以下のような役割になります。

  • Block … コンテナのような大きなかたまり
  • Element … ブロック内の要素
  • Modifier … BlockやElementの装飾

規則

クラス名

.block__element--modifier
  • BlockとElementの間はアンダースコア2つ(__)でつなげる
  • ElementとModifierの間はハイフン2つ(--)でつなげる
  • 各要素が複数の単語になる場合は、ハイフン1つ(-)でつなげる

ファイル名

1つのファイルに1つのBlockを定義します。1つのファイルに複数のBlockを定義するのはNGです。ファイル名は<Block名>.scssにします。

クラス名参照を使う

ElementやModifierクラス名参照(&)を使います。クラス名参照を使うことでBlockやElementの名称を変更する場合に1か所修正するだけで済みます。

// NG
.article {
  // articleの定義
  font-weight: 700;
  
  .article__title {
    // article__titleの定義
    font-size: 1.8rem;
    
    .article__title--red {
      // article__title--redの定義
      color: red;
    }
  }
}
// OK
.article {
  // articleの定義
  font-weight: 700;
  
  &__title {
    // article__titleの定義
    font-size: 1.8rem;
    
    &--red {
      // article__title--redの定義
      color: red;
    }
  }
}

ElementのElementはNG

article__title__authorのようにElementのElementはNGです。このような場合は、article__titlearticle__authorに分割します。SCSSにすると以下のようになります。

// NG
.article {
  font-weight: 700;
  
  &__title {
    font-size: 1.8rem;
    
    &__author {
      color: #ccc;
    }
  }
}
// OK
.article {
  font-weight: 700;
  
  &__title {
    font-size: 1.8rem;
  }
  
  &__author {
    color: #ccc;
  }
}

差分のみ定義する

同じ定義を複数個所にしていると変更したい場合に、すべて変更する必要があり手間になります。共通部分は別に定義することで、重複した定義を減らすことができます。

@extendで共通部をまとめる

@extendを使うと共通部を共通部をまとめることができます。

// font-weightとfont-sizeが重複している
.article {
  font-weight: 700;
  
  &__title {
    font-size: 1.8rem;

	&--blue {
      font-size: 1.8rem;
	  color: #00f;
	}
	
	&--red {
      font-size: 1.8rem;
	  color: #f00;
	}
  }
  
  &__author {
    color: #ccc;
  }
}
// @extendを使って共通部をまとめる
.article {
  
  %__title {
    font-weight: 700;
    font-size: 1.8rem;
  }

  &__title {
    @extend %__title;
    
	&--blue {
      @extend %__title;
	  color: #00f;
	}
	
	&--red {
      @extend %__title;
	  color: #f00;
	}
  }
  
  &__author {
    color: #ccc;
  }
}

@mixinで共通部を定義し@includeで参照する

@mixinを使うと共通部を定義しておくと、@includeした箇所でその定義を参照できます。

// colorとfont-weightが重複している
.article {
  
  &__title {
    color: #ccc;
    font-weight: 700;
    font-size: 1.8rem;
  }
  
  &__subtitle {
    color: #ccc;
    font-weight: 700;
    font-size: 1.3rem;
  }
  
  &__author {
    color: #ccc;
    font-weight: 700;
    font-size: 0.8rem;
  }
}
// 
.article {
  
  @mixin article-font() {
    color: #ccc;
    font-weight: 700;
  }
  
  &__title {
    @include article-font();
    font-size: 1.8rem;
  }
  
  &__subtitle {
    @include article-font();
    font-size: 1.3rem;
  }
  
  &__author {
    @include article-font();
    font-size: 0.8rem;
  }
}

シングルクラスにする

HTMLのclass属性はスペースで区切ると複数のクラスを適用することができます。これをマルチクラスといいます。BEMではこのマルチクラスを禁止しています。BEMではclass属性に指定するクラスは1~2とされています。

<!-- NG -->
<div class="article content red">
  ...
</div>
<!-- OK -->
<div class="article">
 <div class="article__content article__content--red">
  ...
  </div>
</div>

その他

BEMの規則というわけではありませんが、従ったほうが良いルールを以下に記載します。

JavaScriptで参照するクラスにはjs-のプレフィックスをつける

JavaScriptでHTMLを操作する場合、classを参照して操作する場合があります。class名はCSSでもJavaScriptでも参照するので、class名を変更するとCSSにもJavaScriptの両方に影響してしまいます。

そこで、JavaScriptで参照するクラスには明示的にjs-のプレフィックスをつけ、JavaScript専用のクラス(CSSではjs-で始まるクラスにはスタイルをつけない)とします。

こうすることで、class名の変更の影響範囲を抑えることができます。

<!-- NG -->
<div class="toc">
  ...
</div>
<!-- OK -->
<div class="js-toc">
  ...
</div>

最後まで読んでいただきありがとうございます。
また読んでくださいませ。
そんじゃーね。

関連記事

SPONSORED LINK
SPONSORED LINK