【BEM初級編】SassでBEMを記述する場合、なぜ「&」で単語をつなげることが重要なのか?

WEB制作をしていて、CSSのクラス名のつけ方に悩んだ多くの人がたどり着く「BEM」というCSS設計方法があります。

 

便利な反面、メリットをあまり良く分かっていなくて何となく使っているという人も多いのではないでしょうか・・・?

 

今回はSassで「&」を使ってクラス名をつなげる書き方の重要性を考えてみたいと思います。実際の業務であったコードを参考にしていますのでぜひご覧になってみて下さい!

 

まずはさらっとBEMのおさらい

BEMはBlock、Element、Modifierの3つの要素でCSSのクラス名を管理する方法で、

 

block__element--modifier

 

という記述が基本形になります。

ここでポイントになるのが、「__」や「–」で単語をつなげることでCSSがネスト化しないということです。CSSの頭文字の「Cascading(カスケーディング)」、階層化をあえて機能的に使わないのがとても反抗的で面白いところですね!

BEMのメリットは何か?

それではheaderの中にinnerという要素がある場合を考えてみたいと思います。

このinnerにCSSを当てたい場合、下記の2パターンが多いのではないでしょうか。

BEMを使わない場合

<header class="header">
  <div class="inner">
     <a class="btn">CLICK</a>
  </div>
</header>

BEMを使わない場合はHTMLとしてはスッキリとしますね!

 

このHTMLのinnerにスタイルを当てるなら「.header .inner」です。

この記述をもう少し丁寧に訳すと「.headerという要素の中にある.innerという要素」という意味で、2つに分かれた単語が階層化を表しているのが分かると思います。

 

BEMを使う場合

<header class="header">
  <div class="header__inner">
    <a class="header__btn">CLICK</a>
  </div>
</header>

BEMを使う場合は、上記のようなHTMLになり少しクラス名が長く読みづらく感じるかも知れません。

 

innerにスタイルを当てるならCSSは「.header__inner」となります。

今度は「.header__innerという要素」という意味ですね。ここには階層に関する意味は含まれません。あくまで名前を付けるときに「__」でつなげるというのは人間側が決めたルールであって、CSSを解釈するプログラムは階層のことは一切知らず「header__inner」というクラス名の要素という扱いになります。

 

BEMの記述方法はHTML構造(階層)の影響さえも受けません。

 

もちろん運用として問題はありますが(後述します)、.header内に.header__innerがあってもなくてもCSSが有効になります。

さらにCSSの階層的な優先順位(pより.header pが優先され、.header pより.header .inner pが優先される)からも解放されることになります。

 

この階層から解放されている状態が一体なにがメリットなのか?と最初は思うかも知れません。

 

.innerというクラス名がどこかに記述してる場合、.header .innerで意図しないスタイルが当たる可能性がありますが、BEMではこのようなことは起こりません。

.headerや.innerというクラス名とは別の「header__inner」という文字列によるクラスだからです。

 

CSSを局所化する、意図しないスタイルが当たることを回避することにもBEMは有効です。

 

BEMはBlock内でCSSを階層化しない

回りくどい記述を少ししましたが、今回紹介する改善したいSassのコードは下記のようなものです。

.header {
    position: fixed;
    width: 100%;
    z-index: 2000;
    top: 10px;
    .header__inner {
        max-width: 1100px;
        margin: 0 auto;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .header__btn {
            display: flex;
            align-items: center;
        }
    }
}

このSassの問題点はコンパイルして吐き出されるCSSを見るとよりはっきりとします。

.header {
  position: fixed;
  width: 100%;
  z-index: 2000;
  top: 10px;
}
.header .header__inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.header .header__inner .header__btn {
  display: flex;
  align-items: center;
}

これは意図したCSSになっていない可能性が大です。これではせっかくのBEMの効果が有効に使えていません。

 

BEMの命名規則によると.header__innerは、.header内の.innerというエレメントなので、「.header__inner」という名前になっているはずです。

 

なので、

.header .header__innerという記述は助長的になります。

 

これは「&」を使うことでよりブロック内の構造が明確になり、可読性が向上します。

 

.header {
	position: fixed;
	width: 100%;
	z-index: 2000;
	top: 10px;
	&__inner {
		max-width: 1100px;
		margin: 0 auto;
		display: flex;
		align-items: center;
		justify-content: space-between;
	}
	&__btn {
		display: flex;
		align-items: center;
	}
}

この場合出力されるCSSは下記のようになります。

.header {
  position: fixed;
  width: 100%;
  z-index: 2000;
  top: 10px;
}
.header__inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.header__btn {
  display: flex;
  align-items: center;
}

スッキリしましたね!

このようにBlock__Elementの状態で階層化する必要はありません。

 

まとめ

Sassを使ってBEMを記述する場合は「&」を使うことで、

  • 不要にネスト化されたCSSになりにくい。
  • Block内の構造が明確になる。
  • 可読性が向上する

というメリットがあります。ぜひBEMでSassを記述する場合は不要な階層化をしない為に「&」を使っていきましょう!

WEBエンジニアです。 WordPress、PHPを主に使ってWEBサイトやWEBアプリケーションを制作しています。