吉本式BEM設計(BEM設計ベース)

美しいコーディングをするためのガイドラインコンテンツです。

基本的なSCSSの記述方法

本記事からは、SCSSの記述について解説していきます。
BEM設計は、SCSSでの構築を前提とした設計になります。
もしCSSで実装しているのであれば、この機会にSCSSで構築する知識を身につけてください。
このコンテンツでは、SCSSの知識があることを前提として解説します。

吉本式BEM設計(BEM設計ベース)では、SCSSのファイル名、ファイル設計、mixin、モジュール化などについて細かくルールを決めています。
ルールを決めることで、SCSS実装時に発生する迷いが軽減されるはずです。

例えば、
1. SCSSファイルはどういう法則(ルール)で分けているか(モジュール化)
2. どんな時にmixinを使用するか
3. どの要素が、どのSCSSファイルのどこに記述されているかわからなくなる
上に挙げた内容のような問題が出てくる思います。
これらを含め、SCSSの構築ルールを決めることで、迷いがなくなり、スムーズにコーディング作業ができるようになります。
まずは、基本的なところから解説していきたいと思います。

基本的なSCSSの記述方法

前に述べた通り、吉本式BEM設計(BEM設計ベース)はBEM設計をベースにしています。
そのため、基本的にはBEM設計のSCSSの記述方法を踏襲しています。
まずは、BEM設計の基本的な記述として、次のようなマークアップを例にします。

<!-- block -->
<div class="block">
<ul class="block-list">
<li class="block-item"><img src="画像パス"></li>
</ul>
</div><!-- /block -->

上のマークアップをSCSSで記述すると、次のようになります。

.block{
	//div要素のスタイル
	&-list{
		//ul要素のスタイル
	}
	&-item{
		//li要素のスタイル
	}
}

SCSSの機能である「&」を使用し、Block名を引き継いでElement名を指定します。
この記述方法は、Block名が変更になった時に威力を発揮します。
例えば、blockというBlock名が、secに変更になった場合、先頭にあるblockを変更するだけで解決します。

続いて、Modifierがある場合の記述を見てみます。

<!-- block -->
<div class="block _safari">
<ul class="block-list">
<li class="block-item"><img src="画像パス"></li>
</ul>
</div><!-- /block -->

<!-- block -->
<div class="block _chrome">
<ul class="block-list">
<li class="block-item"><img src="画像パス"></li>
</ul>
</div><!-- /block -->

上のマークアップをSCSSで記述すると、次のようになります。

.block{
	$this: &;
	//div要素の共通スタイル
	&-list{
		//ul要素の共通スタイル
	}
	&-item{
		//li要素の共通スタイル
	}
	&._safari{
		//_safari用 div要素のスタイル
		#{$this}-list{
			//_safari用 ul要素のスタイル
		}
		#{$this}-item{
			//_safari用 li要素のスタイル
		}
	}
	&._chrome{
		//_chrome用 div要素のスタイル
		#{$this}-list{
			//_chrome用 ul要素のスタイル
		}
		#{$this}-item{
			//_chrome用 li要素のスタイル
		}
	}
}

ここまでは、BEM設計のルールです。
もし、img要素にスタイルを設定したい場合は、次のようになります。

.block{
	//div要素のスタイル
	&-list{
		//ul要素のスタイル
	}
	&-item{
		//li要素のスタイル
		img{
			//img要素のスタイル
		}
	}
}

これはBEM設計ではNGですが、吉本式BEM設計(BEM設計ベース)では、前回の記事で解説した通り、基本的にはインラインレベルのタグは、タグ指定でSCSS(CSS)を記述する。
とルールを決めています。

BEM設計と吉本式BEM設計(BEM設計ベース)共に、SCSSの記述方法として、Block名が変更になった時に、先頭で指定しているBlock名を変更するだけで済む作りになっていなければいけません。
例えば、次のような記述はNGになります。

.block{
	//div要素のスタイル
	&-list{
		//ul要素のスタイル
		& + .block-list{

		}
	}
	.block-item{
		//li要素のスタイル
	}
}

上の赤字になっている箇所がNG箇所です。
先頭で指定しているBlock名を、先頭以外で指定してしまっています。

続いて、次のようなマークアップを見てみます。

<!-- sec -->
<section class="sec">
<h2 class="sec-tit">タイトル</h2>

<!-- topics -->
<div class="topics">
<p class="topics-txt">テキスト</p>
</div><!-- /topics -->

</section><!-- /sec -->

secというBlockの中に、topicsというBlockが配置されています。
例えば、secの中のtopicsにスタイルを設定したい場合、

.sec{
	//secのスタイル
	.topics{
		//secの中のtopicsのスタイル
	}
}

上のように設定したいかもしれませんが、NGです。
BEM設計のルールに、あるBlockの中に別のBlockを指定してはいけないというルールがあります。
理由は、やはりBlock名が変更になった時の利便性を考慮した設計であるためです。
例えば、上の例で、別ファイルでtopicsに対しスタイルが設定されているとします。

.topics{
	//topicsのスタイル
}

この状況で、topicsの名前を変更しなくていけなくなった場合、topicsを変更するために2つの箇所を変更しなくてはいけなくなりました。
これが2つではなく、3つ、4つ、5つと必要になったらどうでしょうか。
さらに別のBlockに対し、同じような指定をしていたら変更対応が想像するだけで大変です。

あるBlockの中に別のBlockを指定してはいけない。

これはBEM設計のルールですので、吉本式BEM設計(BEM設計ベース)でも前提としてあるルールとなります。
では、次のような場合、どうするでしょうか。

<!-- safari -->
<section class="safari">
<h2 class="safari-tit">タイトル</h2>

<!-- test -->
<div class="test">
<p class="test-txt">テキスト</p>
</div><!-- /test -->

</section><!-- /safari -->

<!-- chrome -->
<section class="chrome">
<h2 class="chrome-tit">タイトル</h2>

<!-- test -->
<div class="test">
<p class="test-txt">テキスト</p>
</div><!-- /test -->

</section><!-- /chrome -->

上のマークアップを見ると、safariというBlockの中にtestというBlockがあり、chromeというBlockの中にも同様に、testというBlockがあります。
例えば、safariとchromeで、testに設定するスタイルを変えたい場合、どのようなSCSSの記述が正しいでしょうか。

.safari{
	//safariのスタイル
	.test{
		//testのスタイル
	}
}

.chrome{
	//chromeのスタイル
	.test{
		//testのスタイル
	}
}

先ほど解説した通り、上の記述はNGです。
このようなケースの場合、testにModifierを設定します。

<!-- safari -->
<section class="safari">
<h2 class="safari-tit">タイトル</h2>

<!-- test -->
<div class="test _safari">
<p class="test-txt">テキスト</p>
</div><!-- /test -->

</section><!-- /safari -->

<!-- chrome -->
<section class="chrome">
<h2 class="chrome-tit">タイトル</h2>

<!-- test -->
<div class="test _chrome">
<p class="test-txt">テキスト</p>
</div><!-- /test -->

</section><!-- /chrome -->

このようにtestにModifierを設定することで、親Blockであるsafariとchromeと切り離すことができます。
ただし、上のようなModifier名は好ましくありません。
なぜなら、Modifier名を親にあたるBlock名と同じにしてしまうと、Block名が変更になった場合、Modifier名も変更しなければいけなくなります。
Modifier名を変更します。

<!-- safari -->
<section class="safari">
<h2 class="safari-tit">タイトル</h2>

<!-- test -->
<div class="test _large">
<p class="test-txt">テキスト</p>
</div><!-- /test -->

</section><!-- /safari -->

<!-- chrome -->
<section class="chrome">
<h2 class="chrome-tit">タイトル</h2>

<!-- test -->
<div class="test _small">
<p class="test-txt">テキスト</p>
</div><!-- /test -->

</section><!-- /chrome -->

Modifier名の付け方ですが、Block名と関連してくるような名前は避け、状態や装飾を示すような名前が良いかもしれません。

.test{
	//testのスタイル
	&._large{
		//_large用のスタイル
	}
	&._small{
		//_small用のスタイル
	}
}

SCSS側の記述は上のようになります。

ここまでが、SCSSの基本的な記述方法となります。