はじめに
前回に引き続き、今回もSassについてのお話をしていきます。
まだSassを導入していない方はこちらからどうぞ
Sassを始めよう:その1[導入]
今回はSass(scss)の基本的な記述として「ネスト」について書いていきます。
目次
- BEMっぽい書き方について
- SassでCSSをわかりやすく
- ネスト
- アンパサンド
- 補完
- 最後に
BEMっぽい書き方について
正確には違いますが、わかりやすく言うとCSS記述をHTMLに構造に似せて作るということです。
親要素をblock、子要素をelement、修飾(block、elementの別の形)をmodifierとして設計します。
cssの書き方としては
.block{@content01;}
.block__element01{@content02;}
.block__element01__element02{@content03;}
.block__element01--modifier{@content04;}
なんて感じで書いたりします。
1段目は親要素のblock
2段目は親要素blockの子要素block__element01
3段目は親要素blockの子要素block__element01の子要素block__element01__element02
このように自分の今いる階層を順番に記述していくのが、今回使う「BEMっぽい」書き方になります。
これを実際にHTMLに当ててみましょう
<div class="block">
<p class="block__element01">
<span class="block__element01__element02">Hello, world!</span>
</p>
<p class="block__element01 block__element01--modifier">
<span class="block__element01__element02">Hello, World!</span>
</p>
</div>
こうしてみると、divの子要素がp、pの子要素がspan、pの修飾(別Ver)が下のpになっているのがわかると思います。
どのclassがどの要素に当たっているのかが階層化されていてわかりやすいですね。
逆にHTMLを見てからCSSを確認しても、どの階層にあるのかがひと目で分かります。
しかし、見て分かる通り、CSSが冗長になってしまいます。
そこでSassの出番となるわけです。
SassでCSSをわかりやすく
先程、BEM記法問題点としてCSSが冗長になると言いましたが、Sassが解消してくれるので問題ありません。
試しに先程のCSSをSass(.scss)として記述し直してみましょう。
.block {
@content01;
&__element01 {
$a: &;
@content02;
&__element02 {
@content03;
}
&--modifier {
@content04;
#{$a}__element02 {
@content05;
}
}
}
}
こんな感じになります。なんとなくプログラミングチックになりましたね。
現時点ではSassの説明を入れていないので、まだ何がなんだかわからないと思いますが、順を追って説明していきたいと思います。
ネスト
ネストはSassを扱う上で基本中の基本となる記述方法です。
やり方はとても簡単。
classのCSSを記述している{}のなかにclassを記述するだけ。
.block {
@content01;
.element {
@content02;
}
}
上記のSassファイルをコンパイルすると
.block {@content01;}
.block .element {@content02;}
こうなります。
blockと、blockの子要素elementとしてコンパイルされました。
仮にCSSを当てるとするなら
<div class="block">
<p class="element">Hello, World!</p>
</div>
このようになりますね。
子要素を定義するとき、親要素をいちいち記述し直さなくてはならない手間が省ました。
& (アンパサンド)
先程の記述では、子要素を定義するときに親要素を呼び出す手間を省きましたが、階層を重ねていくに連れて記述が増える問題は解消していません。
現段階で.block_element01_element02までを記述しようとすると、
.block {
@content01;
.block__element01 {
@content02;
.block__element01__element02 {
@content03;
}
.block__element01--modifier {
@content04;
}
}
}
こうなりますね?
これではまだ冗長でないとは言えないので、& (アンパサンド)を利用します。
この記号は、単体で現在の階層情報を保持しています。
上記のソースを例にすると、
@content01時点では & = ".block"
@content02時点では & = ".block__element01"
となります。
これを踏まえて再度sample.scssを記述してみましょう。
.block {
@content01;
&__element01 {
@content02;
&__element02 {
@content03;
}
&--modifier {
@content04;
}
}
}
かなり短縮できました。
最初の「めんどくさそう」と感じたコードと比較して見ると可読性もかなり向上していると思います。
変数
今回はこの説明で最後になります。
みんなが大好きな変数ですが、Sassでももちろん使用することが可能です。
$a: 100px;
.block01 {
margin-top: $a;
}
.block02 {
padding: $a;
}
こんな感じで記述します。
.block01 {
margin-top: 100px;
}
.block02 {
padding: 100px;
}
コンパイル結果は当然$aに100pxが代入されて出力されます。
これを用いることで、統一させたい値をまとめて記述できるため保守管理性が上がりますね。
なにより一々定数を記述する手間が省けます。
もちろんですが、文字を代入することも出来ます。
$a: solid;
.block01 {
border: $a 1px #000;
}
をコンパイルすると、
.block01 {
border: solid 1px #000;
}
こうなります。
プログラミングを経験した人はお気づきだと思いますが、"solid"を代入するときにクォーテーションがありません。
本来は文字を代入するときにはクォーテーションをつけますが、今回使用している"solid"はただの文字ではなく、borderの状態の一つです。
ですので、ただの文字ではなく状態の1つだ、という意味合いでクォーテーションをつけません。
文字として使うときもクォーテーションいらない場面はありますが、保守性を考えてしっかり区別しましょう。
#{}
これは補完を行うための記述です。
本来、変数は独立して使用しなければなりません。
先程のborderのように状態1つに変数もしくは定数1つといった記述は出来ますが、下記のような記述はできません。
$a: 1;
.block01 {
border: solid $apx #000;
}
$aにはいった変数 + px(ピクセル)として表示したいのですが、これではエラーが発生します。
ではここで補完を使ってみましょう。
$a: 1;
.block01 {
border: solid #{$a}px #000;
}
(コンパイル後省略)
補完はこのように、1つの記述で複数の変数や定数を使いたいときに利用します。
これらを踏まえ、はじめのサンプルコードについての解説をします。
.block01 {
@contemt01;
&__element01 {
@content02;
&__element02 {
@content03;
}
&--modifier {
@content04;
}
}
}
ここのmodifier配下のelement02について、新たにCSSを当てたいとします。
とりあえず、通常のようにアンパサンドでやってみましょう。
.block01 {
@contemt01;
&__element01 {
@content02;
&____element02 {
@content03;
}
&--modifier {
@content04;
&__element02 {
@content05;
}
}
}
}
そしてこれをコンパイルしたものが下になります。
.block01 {
content01;
}
.block01__element01 {
content02;
}
.block01__element01__element02 {
content03;
}
.block01__element01--modifier {
content04;
}
.block01__element01--modifier__element02 {
content05;
}
なにかおかしいですね。
はい、本来は
.block_element01--modifier
のは以下にある
.blockelement01_element02
を変更したいのですが、うまく行ってません。
ここで先程の変数を使用します。
.block {
@content01;
&__element01 {
$a: &;
@content02;
&__element02 {
@content03;
}
&--modifier {
@content04;
#{$a}__element02 {
@content05;
}
}
}
}
変数$aにアンパサンドを代入していますが、これは"&"という文字を代入しているのではなく、値としての'&'、つまりその時点の階層構造を代入しています。
今回は.block__element01内で代入を行っているので$aには.block__element01が代入されます。
そして補完を使用してクラス名を記述していますが、#{$a}__element02は、
.block__element01__element02となります。
そしてその記述は.block__element01--modifier内で行っているため、
.block__element01--modifier配下の.block__element01__element02という階層構造を持ったCSSが吐き出されるわけです。
.block01 {
@content01;
}
.block01__element01 {
@content02;
}
.block01__element01__element02 {
@content03;
}
.block01__element01--modifier {
@content04;
}
.block01__element01--modifier .block01__element01__element02 {
@content05;
}
出力はこんな感じです。
ちゃんと階層化されてますね。
最後に
以上で第2回は終了です。
今回解説した記述を覚えることで、今まで書いていたものは一体何だったんだと思える程、楽にCSSを記述・管理することが出来るようになります。
記述を簡略化することは良いことづくめですので、ぜひチャレンジしてみてください。
備忘録&復習的な感覚で書いていますので、誤字脱字は笑って済ませてくださいお願いします。
その他、わからないこと等連絡してもらえれば相談に乗りますのでぜひどうぞ。