すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

HTML5・CSS3

【HTML5・CSS3】CSS設計のBEMを1から理解してマスターしよう!

ぴっかちゃん
ぴっかちゃん

BEMとは、Block(かたまり)・Element(要素)・Modifier(修飾)の頭文字をとったものです。厳格なclass名の命名ルールが特徴的なCSS設計方法の一つです。

命名規則
1
block__element--modifier

BEMを使うと、以下のようにHTMLを見ただけでスタイルが予測しやすくなります。また、長期的なメンテナンス性が高くなったり、開発スピードを上げることが出来ます。

HTML | BlockとElementの区切り
1
2
3
4
<div class="search"> <!-- Block -->
  <input class="search__input"> <!-- Element -->
  <input class="search__btn"> <!-- Element -->
</div>
HTML | Block(Element)とModifierの区切り
1
2
3
4
<div class="content content--yellow">  <!-- Modifier -->
        <img class="content__img" src="">
        <div class="content__txt">テキスト</div>
</div>

クラス名が長いので通常のCSSでの記述は大変になりますが、この点に関しては、後述するSassで解決することが出来ます。

Webサイトで機能を持つ各パーツ(部品)の要素をまとめて成り立っていることをコンポーネント化と言いますが、BEMは、コンポーネント化する為のフロントエンド設計方法の一つとも言えます。

BEMを構成する3つの要素

BEMを構成する重要な要素に、「Block(ブロック)/Element(エレメント)/Modifier(モディファイア)」があります。

命名規則
1
block__element--modifier
  • Block ‥‥かたまり
  • Element ‥‥要素
  • Modifier ‥‥修飾子

Block(かたまり)を構成するのがElement(要素)です。
Modifier(修飾)は、Block(かたまり)とElement(要素)のスタイルや状態を修飾します。

後述しますが、BlockとElementはアンダースコア2つ(__)で区切り, ElementとModifierはハイフン2つ(--)で区切ります。

Block(かたまり)

1つのWebページ(※1)は、ヘッダー、フッダー、ナビゲーション、サイドバーなどのパーツで構成されています。このパーツにあたる部分がBlockです。Blockは、コンポーネントとも捉えることが出来るでしょう。

bem_1

「Header block」の中にある「Nav block」の様に、blockは他のblockを含めることが出来ます。

(※1)Webページが分からないという方は、HTMLが使用されている具体例を参考にして下さい。

BlockをBEMで定義する

検索フォームである「Search block」をBEMで書くと次の様になります。

HTML | Blockを定義する
1
2
3
4
<div class="search"> <!-- Block -->
  <input class="search__input"> <!-- Element -->
  <input class="search__btn"> <!-- Element -->
</div>

上記のコードは、searchのBlockに2つのElement(input,btn)が属しています。

BlockのsearchとElementのinputとbtnは、二重アンダースコア(__)で区切ります。

Element(要素)

Elementは、Blockを構成する要素です。
検索フォームのSearch blockの構成を確認して見ましょう。

Element(要素)

「input」と「submit」は「Search block」を構成する要素(Element)になります。

BlockをElementで定義する

ElementはBlockに属しているので、クラス名には必ずBlock名を含めます。
これにより、どこまでがBlockなのか一目で理解する事が出来ます。

HTML | Elementを定義する
1
2
3
4
<div class="search"> <!-- Block -->
  <input class="search__input"> <!-- Element -->
  <input class="search__btn"> <!-- Element -->
</div>

Elementを繰り返し利用する

下記のNav blockには複数のElementが属しています。

bem_3

「Nav block」のElementの様に「ElementはBlock内で繰り返し使うことが出来ます。」

Modifier(修飾)

既存のBlockやElementに対して、一部見た目や状態を変えたい場合に、新規に作り直すのではなくModifierを使います。

bem_4

BlockやElementが繰り返し使われているなどで、2種類以上存在する場合にModirierを使います。

Modifierの種類とは?

Modifierは、「Blockに対して使うModifier」と「Elementに対して使うModifier」があります。また、Modifierは名前である「key」と値である「value」を持ちます。

Modifierの種類
1
2
3
4
5
6
7
8
9
<!-- Blockに対して修飾 -->
Block--Modifier

<!-- Elementに対して修飾 -->
Block__Element--Modifier

<!-- Modifierのkey,valueを指定する場合 -->
Block--key_value
Block__Element--key_value

BlockやElementの後にハイフン2つで区切って定義します。
key, valueを定義する場合は、keyvalueをアンダースコア1つで区切ります。

Blockに対してModifierを定義

構成要素自体を変えたい時にBlockに対してModifierを使用します。例えば、下記の様に赤枠で囲まれているContent blockがあります。

Blockに対してModifierを定義

このContent blockは繰り返し使われていますが、片方だけ背景を黄色にしたい場合にModifierが必要になります。

HTML | Modifierを追加する
1
2
3
4
5
6
7
8
9
<div class="content">
  <img class="content__img" src="">
  <div class="content__txt">テキスト</div>
</div>

<div class="content content--yellow">  <!-- Modifierを追加 -->
  <img class="content__img" src="">
  <div class="content__txt">テキスト</div>
</div>

BlockにModifierを定義するときは、「Block--Modifier」でハイフン2つで区切ります。

Elementに対してModifierを定義

Elementのバリエーションを作る場合は、Modifierが必要になります。例えば、Nav blockにあるナビゲーションの様に、現在地を他のメニューと変える時にModifierを使います。

bem_6

HTML | ElementにModifierを定義
1
2
3
4
5
<ul class="nav">
  <li class="nav__item--state_current">Home</li>  <!-- Modifier -->
  <li class="nav__item">About</li>
  <li class="nav__item">Contact</li>
</ul>

Modifierをkey(stateは状態)とvalue(currentは現在地)を使うと、そのクラスが何を表しているのか理解出来て可読性が良くなります。

その他の例

Modifierの例をもう少し見てみましょう。下記の様な登録フォームはWebサイトでよく見ますが、ページによってボタンのスタイルを一部変えたい場合にModifierが使えます。

「form__button」は、Sassで下記の様にスタイルが指定されています。(Sassについては、後述します。)

bem_8

HTML | 登録フォームの1部を抜粋しています
1
2
3
4
<form class="form">
  <input input type="text" class="form__name">
  <input type="submit" class="form__button">
</form>

下記の様にボタンの背景色を赤や青に変更したり、角を丸くします。

HTML | 登録フォームの1部を抜粋しています
1
2
3
4
5
6
7
8
9
10
11
<!-- この部分に一部変更するクラスを追加します。-->
<input type="submit" class="form__button">

<!-- 背景を赤色にする -->
<input type="submit" class="form__button--red">

<!-- 背景を青色にする -->
<input type="submit" class="form__button--blue">

<!-- 角を丸くする -->
<input type="submit" class="form__button--round">

スタイルは省きますが、それぞれ「form_button--red」、「formbutton--blue」、「form_button--round」に独自のスタイルを追加します。

これにより、既存のスタイル + 独自のスタイルを取り入れる事が出来ます。

セパレーターと命名規則

セパレーターとは、Block、Element、Modifierを区切っている「アンダースコア2つ区切り(__)」や「ハイフン2つ区切り(--)」の区切り文字のことです。

セパレーターには、主に3種類あります。

  1. BlockとElementの区切り
  2. Block(Element)とModifierの区切り
  3. 単語区切り

セパレーターはBEMで重要な項目なので、もう一度1つ1つ整理していきましょう。

1. BlockとElementの区切り

BlockとElementは、アンダースコア2つ(__)で区切ります。

HTML | BlockとElementの区切り
1
2
3
4
<div class="search"> <!-- Block -->
  <input class="search__input"> <!-- Element -->
  <input class="search__btn"> <!-- Element -->
</div>

2. Block(Element)とModifierの区切り

Block(Element)とModifierは、Block(Element)の後にModifierをハイフン2つ(--)で区切ります。

HTML | Block(Element)とModifierの区切り
1
2
3
4
<div class="content--yellow"><!-- Modifier -->
  <img class="content__img" src="">
  <p class="content__txt">テキスト</p>
</div>

また、Modifierでkeyとvalueを指定する場合は、keyとvalueをアンダースコア1つ(_)で区切ります。

HTML | keyとvalueの区切り
1
2
3
4
5
 <ul class="nav">
    <li class="nav__item--state_current">Home</li>  <!-- keyとvalue -->
    <li class="nav__item">About</li>
    <li class="nav__item">Contact</li>
  </ul>

3. 単語区切り

BlockやElementのクラス名を、2つ以上の単語で表す場合に、ハイフン1つ(単語-単語)で区切ります。

HTML | 単語区切り
1
2
3
4
<div class="content-left"> <!-- 単語区切り -->
  <img class="content-left__img" src="">
  <div class="content-left__txt">テキスト</div>
</div>

BEMと親和性の高いSassを使用する

BEMのデメリットは、クラス名が長くなりCSSで記述する際は冗長になってしまう点でしたが、BEMと親和性の高いSassを利用することで、CSSよりも非常に効率良くコーディングする事が出来ます。

Sassが分からない方は、「Sassを攻略してコーディングを効率良く」を参考にしてください。

セパレーターの親子関係

BEMでは、Block、Element、Modifierに対してセパレーターを使って区切っていました。この「区切り元と区切り先」はそれぞれ「親と子」の関係になります。

HTML | セパレーターで見る親子関係
1
2
3
4
<div class="search"> <!-- Block -->
  <input class="search__input"> <!-- searchが区切り元、inputが区切り先 -->
  <input class="search__btn"> <!-- Element -->
</div>

search_inputの場合は、「searchが親」で「inputが子」になります。
<mark class="l-detail
_marker">この親子関係をSassの「&」を使うことによって、効率的に記述出来るのです。

BEMをSass(SCSS)で定義する

BEMで定義した親子関係に対して、Sassの「&」を使うと、ネスト構造(入れ子)で記述することが出来ます。

SCSS | BEMを使ったSCSS
1
2
3
4
5
6
7
8
9
10
11
.search {
  margin: 30px;

  &__input {
    font-size: 18px;
  }

  &__btn {
    color: red;
  }
}

上記がCSSにコンパイルされると、下記の様になります。CSSで書くとこの様に助長になってしまいます。

CSS | CSSへコンパイルした場合 -->
1
2
3
4
5
6
7
8
9
.search {
  margin: 30px;
}
.search__input {
  font-size: 18px;
}
.search__btn {
  color: red;
}

ネストした「&」の後にセパレーターを忘れてしまうと、親子関係とみなされずCSSが上手くコンパイルされないので注意してください。

「&」を使う際の注意点

BEMでは、Blockの中にBlockを含める事が出来ました。
下記の例では、「Header block」の中に「Logo block」や「Nav block」が含まれています。

&を使う際の注意点

しかし、SassではBlockをネストしてスタイルを記述してはいけません。
何故なら、Blockはどこかに依存する事なく、完全に独立させなければいけないからです。別の場所に移しても単体で動作する必要があります。

「Modifier」と「placeholder selector」

placeholder selector(プレースホルダーセレクタ)とは、再利用できるスタイルセットを%キーワードで指定する@extend専用のセレクタです。(@extendについては、@extendディレクティブを参考にしてください。)

SCSS | プレースホルダーセレクタを定義する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
%default-item {
  // 共通するスタイルを定義
  background-color: yellow;
  color: #53579F;
  padding: 10px;
}

.nav {
  &__item {
      @extend %default-item;

    &--state_current{
      //Modifierのスタイルを定義
      @extend %default-item;
      background-color: pink;
    }
  }
}

Modifierは、placeholder selectorを使って差分のみ記述します。上記がCSSにコンパイルされると下記の様になります。

CSS | CSSへコンパイルした場合
1
2
3
4
5
6
7
8
9
.nav__item, .nav__item--state_current {
  background-color: yellow;
  color: #53579F;
  padding: 10px;
}

.nav__item--state_current {
  background-color: pink;
}

placeholder selectorで定義した共通のスタイルを@extendで継承して、Modifierの箇所で変更するスタイルを定義する事で、保守性のある綺麗なコードを保つことが出来ます。

この記事のまとめ

  • BEMとは、Block(かたまり)・Element(要素)・Modifier(修飾)の略語のこと
  • BEMの厳格なclass名の命名ルールによって、HTMLを見ただけでスタイルが予測しやすいメリットがある
  • Block、Element、Modifierを区切っている「アンダースコア2つ区切り(__)」や「ハイフン2つ区切り(--)」の区切り文字のことをセパレーターと言う

16

わかった!