今回はBEMを高速で書いていく方法を書いていきます。実際に現場で使われている手法となります。
CSS設計のBEMに徐々に慣れてくると、もっとBEMを効率良く書けないかな?と思うのですが、そういう時に使えるのがSASSを活用してBEMを効率良く書く方法です。
僕自身も常駐先でしごかれてSASSを使ったBEMの効率のいい書き方を身に付けることができたので、今回はその現場で使っているSASSを使ったBEMの書き方をマスターしていってもらえればと思います。
BEMで管理はしやすくなったんだけど、もう少しBEMでコーディングスピード上げる方法はないかな??
SASSを活用してBEMを書くとかなりコーディングスピードを上げることができるので、BEMに慣れてきたら、効率アップの為にSASS導入も視野に入れていくといいですね。
少しSASSの書き方に慣れるまでは時間が必要ですが、慣れるとかなり効率よくBEMを書くことができます。
まだCSSのBEM記法をよくわからないという人はまずは下記記事を参考にしてBEMのイメージを作ってもらえればと思います。
今回、SASSを使ってBEMを書いていくということなので、まずはSASSの環境構築から作っていきたいと思います。
僕はフリーランスコーダーとして4年ほど経過して、ディレクター兼コーダーとして年間50サイト以上を手掛けている現役コーダーになります。
BEMを効率良く書くためにSASSを導入しよう
まずはSASSを使える環境にしていきたいと思います。
SASSを使えるようにするツールは色々あるとは思うのですが、今回は一番設定が簡単なテキストエディタvscodeにプラグインを入れてSASSを使えるようにしたいと思います。
SASSを使えるようにするプラグインをvscodeにインストールしよう
まずはvscodeの左メニューでプラグインのインストールをします。
左メニューのプラグインメニューをクリックして、「Live Sass Compiler」と検索をかけます。
「Live Sass Compiler」が出てきたら、インストールをクリックしましょう。
HTML、CSSは前回のモディファイア編のソースをそのまま使って作業していきます。
次はstyle.cssと同じディレクトリの階層に「style.scss」というscssファイルを作ります。
「style.scss」を作ったらstyle.cssに入っているCSSをすべて、「style.scss」にコピペします。
コピペが完了したら、上記画像の③Watchingをクリックします。
style.scssが空のまま「Watching」をクリックするとコンパイルが始まって、style.cssの内容が消えてしまうので、必ずstyle.css → style.scssにCSSを移行してから「Watching」をクリックしましょう。
「Watching」を開始したら試しに「style.scss」を変更してみましょう。Watchingの箇所が「Success」に変わったら問題なくstyle.cssにコンパイルが完了しております。「Watching」をクリックした後は変更する度に自動コンパイルしてくれます。めちゃ簡単ですねw
基本的にはここからは「style.scss」だけを変更します。「style.css」はまったく触らないことになります。
コンパイル後は「style.css.map」が生成されていると思います。
「mapファイル」はブラウザにSCSSファイルのスタイルの位置を伝えるためのファイルなのですが、僕自身の好みですが、mapファイルは特に無くても問題ないので出力しないように設定しておきます。
mapファイルを出力しない理由は、CSSファイルが増えるとその分、mapファイルが増えてディレクトリ内がゴチャついてくるからになります。
あと、各ブラウザ表示対策のベンダーフレックスを自動出力する設定もしておきたいと思います。
まだまだSASSの細かな設定はあるのですが、今回はその2つの設定でいいかな?と思います。
SASSのコンパイルの設定を変更しよう
まずはvscodeの左下の「歯車マーク」をクリックして、「設定」をクリックしていきます。
すると「設定」のタブが開くので、「設定」のタブの右上の下記画像の赤枠のアイコン部分をクリックします。
すると、「settings.json」ファイルが開きます。この「settings.json」で各プラグインの設定を変更できます。settings.jsonの一番下にLive Sass Compilerの設定を書き込んでいきます。
「settings.json」ファイルの一番下ですが、全体が中括弧「{}」で囲まれてるので、中括弧の中に追記していきましょう。
まずはmapファイルを出力しない設定を追記します。
"liveSassCompile.settings.generateMap": false,
次はベンダーフレックスを自動出力する設定を追記。
"liveSassCompile.settings.autoprefix": [
">= 5%",
"last 2 versions"
],
記述の最後には必ずコンマ「,」を設置するのを忘れないようにしましょう。区切りにコンマが無いとエラーになるので、注意して記入してください。
これで一旦出力されたmapファイルを削除して、もう一度Watchingでコンパイルしてみましょう。
コンパイル後、style.cssをみるとベンダーフレックスが出力されていると思います。そして、mapファイルは出力されてないですね。
SASSを導入すると自動でベンダーフレックスを付加してくれるのもかなりのメリットですね。
これで一旦、SASSの設定が完了です。次からはSASSを使ってBEMを効率良く書いていきましょう。
SASSを使ってBEMを効率良く高速で書こう
SASSを使える環境になったので、モディファイア編で使ったCSSをSASSの書き方に変更していきましょう。
まずは変更前のstyle.scssになります。
.main {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* dialog block start */
.dialog {
max-width: 780px;
width: 100%;
background: #fff;
border-radius: 14px;
filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.4));
}
.dialog__inner {
padding: 40px;
}
.dialog__heading {
text-align: center;
}
.dialog__text {
margin: 0;
}
.dialog__btnBox {
display: flex;
justify-content: center;
align-items: center;
gap: 40px;
margin-top: 30px;
}
/* dialog block end */
/* btnSquare block start */
.btnSquare {
max-width: 180px;
width: 100%;
}
.btnSquare--large {
max-width: 220px;
width: 100%;
}
.btnSquare__link {
display: block;
background: #fff;
border: 1px solid #666;
color: #333;
text-decoration: none;
text-align: center;
padding: 10px 5px;
transition: all 0.25s ease;
}
.btnSquare__link--gray {
background: #dcdcdc;
}
.btnSquare__link:hover {
color: #fff;
background: #666;
}
.btnSquare__text {
font-size: 14px;
}
/* btnSquare block end */
前回のモディファイア編と同じCSSの内容ですね。これをSASSのクラス名を切り離せる機能を使い書いていきます。
SASSのクラス名を切り離す機能を使い効率よくBEMを書いていこう
上記の書き方からSASSの機能を使ってBEMを効率よく下記のように書き換えてみました。
.main {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* dialog block start */
.dialog {
max-width: 780px;
width: 100%;
background: #fff;
border-radius: 14px;
filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.4));
&__inner {
padding: 40px;
}
&__heading {
text-align: center;
}
&__text {
margin: 0;
}
&__btnBox {
display: flex;
justify-content: center;
align-items: center;
gap: 40px;
margin-top: 30px;
}
}
/* dialog block end */
/* btnSquare block start */
.btnSquare {
max-width: 180px;
width: 100%;
&--large {
max-width: 220px;
width: 100%;
}
&__link {
display: block;
background: #fff;
border: 1px solid #666;
color: #333;
text-decoration: none;
text-align: center;
padding: 10px 5px;
transition: all 0.25s ease;
&--gray {
background: #dcdcdc;
}
&:hover {
color: #fff;
background: #666;
}
}
&__text {
font-size: 14px;
}
}
/* btnSquare block end */
SASSは「&」を使うことでクラス名を途中で切り離して書くことができます。その特性を使ってブロック内のエレメントとモディファイアのクラス名を途中で切り離して書いています。
ブロックの中にエレメントとモディファイアのクラス名を切り離して書くことで、ブロックの範囲内がよりわかりやすくなり、CSSの記述量も圧倒的に減らすことができます。普通のCSSだとブロック名を何度も書かないといけなくなっているのが、SASSだとブロック名は一度書くだけでOKとなります。この辺りBEMとSASSがかなり相性がいいところですね。
こちらのクラス名は適当に途中で切ってるのではなく、ブロック名の終わりの部分から切るように統一しております。このように切る位置を決めることで書き方に統一性を出して、さらにみやすくしています。
モディファイアをSASSの機能を使って効率良く書いてみよう
モディファイアもSASS機能を使うと効率良く書くことができます。
SASSは@extend クラス名;と書くことでスタイルの継承ができます。モディファイア部分を下記のように変更してみてください。
.main {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* dialog block start */
.dialog {
max-width: 780px;
width: 100%;
background: #fff;
border-radius: 14px;
filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.4));
&__inner {
padding: 40px;
}
&__heading {
text-align: center;
}
&__text {
margin: 0;
}
&__btnBox {
display: flex;
justify-content: center;
align-items: center;
gap: 40px;
margin-top: 30px;
}
}
/* dialog block end */
/* btnSquare block start */
.btnSquare {
max-width: 180px;
width: 100%;
&--large {
max-width: 220px;
width: 100%;
}
&__link {
display: block;
background: #fff;
border: 1px solid #666;
color: #333;
text-decoration: none;
text-align: center;
padding: 10px 5px;
transition: all 0.25s ease;
&--gray {
@extend .btnSquare__link;
background: #dcdcdc;
}
&:hover {
color: #fff;
background: #666;
}
}
&__text {
font-size: 14px;
}
}
/* btnSquare block end */
&--grayモディファイアに「@extend .c-btnSquare__link;」を追記しました。こちらどういうことが起こるかというと、@extendを使うことで.c-btnSquare__linkのスタイルを引き継ぐこと(継承)ができます。
なので、同じようにスタイルを書かなくても@extend クラス名;と書くことでスタイルを継承できますので、非常に便利です。
@extendを使うことで、本来のCSSの場合モディファイアを作ったら同じスタイルをモディファイアにすべて書くか、変更のスタイルのみ書いてHTMLにクラスを2つ設置するか?という2択だったのが、@extendを使うと1行でスタイルを受け継ぐことができるので、少ないCSS量で、HTMLはモディファイアのクラスを1つだけにすることができます。
上記のように@extendを使うとHTMLもモディファイアクラス1つだけでシンプルになっています。
この@extendですが、非常に便利なのですが、注意したいのが@extendを使い過ぎるとコンパイル後のCSSがごちゃごちゃになることです。
@extendのコンパイル後のCSSをみると継承元クラスにコンマが追加されています。こちらをもしモディファイアを作るごとにすべてのモディファイアに@extendし過ぎるとコンパイル後のCSSがよくわからないコンマだらけのCSSになってしまいます。
なので、@extendさせるスタイルを決めて@extendを設置する方がいいかと思っております。今回の例でいうと背景色の変更のモディファイアのみに@extendを設置するなど、ある程度@extendさせるスタイルを決めるといかもです。
どちらにせよ、2つのモディファイアをひとつのHTMLに設置する場合はクラスが複数になるので、それでいいんじゃないかと思っております。
特定のスタイル変更のモディファイアのみに@extendさせるなどのルールが必要。
モディファイア内にモディファイアを作ることはNGなんですが、モディファイアにエレメントをネストするのはOKとなります。モディファイア内にエレメントを新規で定義するのではなく、既存エレメントをモディファイア内にネストするということになります。
ちょっとテキストでいってもわかりづらいかもですので、実際に設置してみましょう。
モディファイアにエレメントを入れ子にしてみよう
「btnSquare」ブロックの&--largeモディファイアに既存エレメントを入れ子にして、スタイル変更していこうと思います。&--largeモディファイアの場合、ボーターが太くするのと、フォントサイズを大きくする調整を入れていきたいと思います。
style.scssを変更してみました。
.main {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* dialog block start */
.dialog {
max-width: 780px;
width: 100%;
background: #fff;
border-radius: 14px;
filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.4));
&__inner {
padding: 40px;
}
&__heading {
text-align: center;
}
&__text {
margin: 0;
}
&__btnBox {
display: flex;
justify-content: center;
align-items: center;
gap: 40px;
margin-top: 30px;
}
}
/* dialog block end */
/* btnSquare block start */
.btnSquare {
max-width: 180px;
width: 100%;
&--large {
max-width: 220px;
width: 100%;
.btnSquare__link {
border: 3px solid #666;
padding: 7px 5px;
}
.btnSquare__text {
font-size: 18px;
}
}
&__link {
display: block;
background: #fff;
border: 1px solid #666;
color: #333;
text-decoration: none;
text-align: center;
padding: 10px 5px;
transition: all 0.25s ease;
&--gray {
@extend .btnSquare__link;
background: #dcdcdc;
}
&:hover {
color: #fff;
background: #666;
}
}
&__text {
font-size: 14px;
}
}
/* btnSquare block end */
&--largeモディファイアに既存エレメントを付加して、&--largeモディファイアのスタイル変更範囲を増やしました。みていただけるとわかると思うのですが、エレメントを入れ子にして書くことで、モディファイアひとつで下層エレメントもまとめて変更できます。これは結構便利な書き方になりますね。
表示するとモディファイアを入れたことで、下記のような感じになりました。
&--largeモディファイアにエレメントを入れ子にする場合はクラス名を切らずにそのまま書きます。ブロック直下のエレメント、モディファイアは切って書き、2段目以降の入れ子にをする場合は切らないように書きます。2段目のネスト構造のクラスを切らない理由は単純に可読性を損なわないようにするためです。
クラスを切るのはブロックの直下のエレメント、モディファイアだけにして、それ以降ネストする場合はクラス名を切らないようにすると、視認性を維持しつつ、SASSでBEMを書くことができます。
2段以降のネストはあまりないとは思いますが、SASSはクラス名を切れることができて便利ですが、切り過ぎると可読性を損うので、切る部分に対してルールを作っておくことが可読性を落とさないために非常に重要になってきます。
ブロック直下のエレメント・モディファイアのみクラス名を切るルールにするとみやすくSASSをBEMで書くことができる。
モディファイアとエレメントの位置を決めて管理しよう
大きめのブロックを作るとモディファイアやエレメントが増えてきて管理が大変になることもあります。
管理が少しでも楽になる提案が、モディファイアとエレメントの位置を決めておき、モディファイア、エレメントをまとめて書いておくこと、になります。
今回のコードで説明すると順番的にはモディファイアが最初に書き、その後にエレメントを書きます。
上記のような順番のルールを設定しておくと、モディファイアがひとまとまりになって先に書いてあって、その後にエレメントがまとまって後に書いている状態を作ることができます。
そのようにモディファイアが先で、エレメントが後のような簡単なルール決めをしておくと後々コードを探すのも楽になるし、コードの配置場所で頭を悩ますことも無くなるので、ぜひ採用してみてください。
ページ数の多いサイト制作になるとBEMの管理も難しくなってきます。そういう時に便利なのがSASSのファイル分け機能です。具体的にはSASSのファイル分け機能を使って、ブロックごとにファイルを分ける仕様にすることで管理しやすくすることができます。
次はBEMを管理しやすくするためにSASSを使ってブロックごとにファイル分けていきましょう。
SASSを使ってブロック単位でファイル分けすれば管理が楽になる
現場のBEMはSASSを使ってブロックごとにファイル分けして管理しています。なぜそうするかというとブロックをファイル分けすると目的のCSSがすぐに見つかるし、大規模サイトになればなるほどCSSの管理がしにくくなるので、ファイル分けすることで管理しやすい状態を維持できるからです。
では実際に今までのBEMのブロックをファイル分けしてみましょう。
まずはbaseフォルダとcomponentsフォルダを作っていきます。
base、componentsフォルダを作ったら、まずはbaseフォルダの中には_base.scssファイルを作り、componentsフォルダ内には、_dialog.scssファイルと、_btnSquare.scssファイルを作ります。
scssファイルの先頭についているアンダースコア(_)を付けるのは、アンダースコアを先頭に付けたファイル自身はコンパイルをしないということになります。なので、コンパイルされずにbase.cssは出力されないことになります。
要は先頭にアンダースコアを付けるか付けないかでコンパイルするかしないかを制御できるということです。
componentsフォルダ内のファイルはファイル名にブロック名を付けています。そうすることでこのブロックはこのファイルにあることがすぐにわかるようになります。
components内のファイル名はブロック名をそのまま使ってファイル名を付けておきます。そうすることで、目的のブロックのCSSをすぐにみつけることが可能になります。
それでは次はstyle.scssファイルに入っているCSSコードをコピペで移していきましょう。
dialogブロック部分のCSSコードを_dialog.scssにコピペして、btnSquareブロックの分は_btnSquare.scssにコピペします。mainタグのみ_base.scssに移動しましょう。_base.scssはそのページのベースとなるスタイルを入れる役割のファイルになります。
CSSコードを3つのファイルに移動できたら次は、その3つのファイルをstyle.scssで読み込む設定にしていきましょう。
style.scssののCSSはすべてを別ファイルに移したので一旦削除しましょう。
その代わりに別ファイル化したCSSを読み込む設定を書き込んでいきます。まずは下記のように設定していきましょう。
/* base ---------------------------------------
-------------------------------------------- */
@use 'base/_base';
/* components ---------------------------------
-------------------------------------------- */
@use 'components/_dialog';
@use 'components/_btnSquare';
SASSで別ファイルを読み込む場合は「@use」と書き始めます。その後にシングルクォテーションで囲って、読み込むファイルのパスを書きます。これで3ファイルとも読み込むことが完了です。
@useで読み込みのパスを書く場合は「.scss」は省略して書くことができます。
この読み込む順番はベースのCSSを先に書き込むのがセオリーになります。CSSの優先順位的にベースのCSSから書きます。
コメントアウトはコンパイルされるCSSファイルに書き込みたいコメントは「/* */」の書き方で書くとコンパイル後もコメントが出力されます。出力したくないコメントアウトは「//」スラッシュ2つで書くことでコンパイル後はコメントが表示されないです。
・CSSファイルに表示したいコメントは/* */で書く
・CSSファイルに表示したくないコメントは//で書く
こちらで一度、SASSを動かしてみましょう!エラーなく動作すると下記の表示になると思います。
このようにSASSの機能でブロックごとにファイルを作って切り分けるとさらに管理しやすくなります。ファイル分けしておくことで、CSSファイルを増やしたときもSCSSファイルの読み込み箇所を変えることで簡単にCSSコードを振り分けられるので、かなり効率よくBEMを管理できるようになります。
SASSとBEMはこのようにファイル分けの観点からもかなり相性がいいので、大規模サイトほどSASSとBEMの使用がかなり多いのが現状になりますね。
・_base.scssを使ってページのベースのCSSを入れる
・componentsフォルダにブロック名を付けたファイル(_btnSquare.scssなど)を作り、ブロックごとにCSSコードを収納
・style.scssで@useを使い、ファイル分けしたCSSを出力する
SASS+BEMを使えば運用しやすく効率がかなりアップします
今回SASS+BEMの組み合わせの使い方を解説しましたが、これをマスターすればかなり運用性が高く、効率的なコードを書くことができ、かなり強力な武器となってくれるでしょう。
実際、僕も最初は独学でSASS+BEMを学んでて中途半端の知識でしたが、会社の現場に入ってかなり基礎を叩き込んでいただき、SASS+BEMの使い方もある程度理解が進んでくると、クライアントワークのお客さんにかなり喜んでいただけるようになりました。
実際、制作会社の下請けなどで入ると制作会社さんはプロなので、納品物のHTML、CSSをまじまじとみられていると思います。それで綺麗なコードを書いていると、この人になら安心して案件をお願いできると思われるのか、かなりの確率で仕事のリピート依頼をしていただけるようになりました。
初めは慣れなくて、悩むことが多いと思いますが、今回書いていったBEM編を何度も繰り返し見直してもらうと、徐々に慣れていって、綺麗なコードで運用性も維持し、効率良くコーディングできようになってきますので、ぜひともまずはトライしていただければと思います。
今回のBEMの記事はこれで完結となります。
最後までお読みいただきまして誠にありがとうございました!
下記記事でBEM記法の書籍を紹介してますので、BEMについてもっと詳しく学習したい人はおすすめの本ですので良かったら読んでみてください。
※上記書籍ではモディファイアはアンダースコア1つと書いてますが、実際の現場はモディファイアはハイフン2つなので、その点にだけ注意してください。
上記書籍ですが、各パーツでのBEMの書き方が詳しく書かれていて基本的なHTML構造を学べるので、高額となりますが買って損はないと思います。
BEMの復習をするなら下記からどうぞ!
これまでのコードをダウンロードできるようにしておきましたので下記ボタンからダウンロードして直接コードを確認できます。
もし今回わからない箇所などありましたら、下記からご相談いただけましたらありがたいです。