はじめに
CSS in JS
やCSS Modules
が主流の時代に、今さらBEM
かよ。。の記事になるかもしれませんが、Chainable BEM modifiers
やBEVM
について日本語で書かれている記事があまり無かったこともあり、自分の取り入れ方の紹介も兼ねて書いてみることにしました。
対象読者
- SCSSが使える(読める)方
- BEM(MindBEMding)について理解があり、実際に使ったことがある方
- MindBEMdingの
Modifer
の書き方に煩わしさを感じている方
Chainable BEM modifiers
is 何?
Jordan Lewisという方が、従来のBEMのModifierに対する課題を解消するために提唱されたソリューションです。
因みに、現時点でJordan Lewis
でググると、一番上にはオーストラリア式フットボール選手がヒットしますが、多分その人ではありません。
Chainable BEM modifiers
https://webuild.envato.com/blog/chainable-bem-modifiers/
スライド
https://www.slideshare.net/jordanlewiz/chainable-bem-modifiers
Chainable BEM modifiersの書き方
BEMのModiferを表すクラスセレクタを、接頭辞-
に続けて名前空間(key)、値(value)のセットで書きます。
Chainable BEM modifiersの例(公式な書き方)
<!-- Large green button -->
<button class="btn -color-green -size-large">
SCSSをつかってルールセットを書くと、次のようになります。
.btn {
font-size: 20px;
background-color: grey;
&.-color-green {
background-color: green;
}
&.-size-large {
font-size: 30px;
padding: 10px;
}
}
従来のBEMのModiferの書き方
マルチクラスとシングルクラスでそれぞれ同じものを表すことができます。
Chainable BEM modifiersはマルチクラスの書き方に近いです。
マルチクラス(クラスが連鎖している)
<button class="btn btn--color-green btn--size-large">
.btn {
font-size: 20px;
background-color: grey;
&.btn--color-green {
background-color: green;
}
&.btn--size-large {
font-size: 30px;
padding: 10px;
}
}
シングルクラス
<button class="btn--primary">
.btn {
font-size: 20px;
background-color: grey;
}
.btn--primary {
@extend .btn;
background-color: green;
font-size: 30px;
padding: 10px;
}
上記のマルチクラスとシングルクラス、それぞれ表現方法は違えど、適用されるスタイルは結果的に同じものになります。
それぞれに適したシナリオが有りますが、Modiferを使った異なる規約が存在するのは混乱を招く、とLewis氏は嘆いています。
Whilst both techniques are valid, they lend themselves for use in different scenarios. Plus, having two conventions using identical syntax in the same codebase is a recipe for confusion.
BEVMの登場
そこで登場したのがBEVM
で、V
はVariationを表します。
従来のModiferを使ったシングルクラスのアプローチを、代わりにVariationに置きかえよう、という試みです。
Modiferも含めると、block__element--variation -modifier
という構文になります。(Element
が無い場合にはblock--variation
)
なので、Variationを表す書き方は従来のBEMのModiferと同じになりますが、Modifierで扱ってきたものを、Variation(基本のものとは明確に異なる形態)とModifer(基本のものとは一部または少しの変化が生じたもの)に分けて、それぞれ扱いを区別しようという考えです。
実際どう使っているか?
結論、自分はBEVMのV
は使っておらず、ModiferだけChainable BEM modifiersの考えに近いものを取り入れています。
Chainable BEM modifiersでは、
- 名前空間(key)と値(value)の組み合わせでセレクタ名を書く
- 例:
-color-red
,-size-large
- 例:
- 基本となるモジュール(BlockまたはElement)に対して、同じCSSプロパティを2回以上変更してはいけない
- OK例:
<div class="btn -color-red -size-large">
- NG例:
<div class="btn -color-red -color-green">
- OK例:
がルールとして定められています。
課題感としては、何がVariationで何がModiferなのかを区別するのが面倒なことと、Block、Element、Modifierに続けて新しい書き方を覚えたくない、覚えさせたくないということ。
ただ、それならば従来のMindBEMdingの書き方に戻るのかと言うと、それはちょっと勿体なく、Chainable BEM modifiersのおいしいところを取り入れることにしています。
従来のMindBEMdingでは、
<button class="btn btn--color-green btn--size-large">
と書いていたのを、Chainable BEM modifiersを使うと
<button class="btn -color-green -size-large">
となり、Modiferを表すセレクタからbtn-
が外れただけでエコになっているのですが、これを更に名前空間(key)を省略する形で
<button class="btn -green -large">
としています。
SCSSでは、次のようになります。
.btn {
font-size: 20px;
background-color: grey;
&.-green {
background-color: green;
}
&.-large {
font-size: 30px;
padding: 10px;
}
}
最初のMindBEMdingのセレクタ名からbtn--color
、btn--size
が外れて、かなりエコになりました。
また、従来のシングルクラスのように、次のような書き方もすることがありますが、なるべくHTMLを見ただけでどんなスタイルなのかが予測できるのが好ましいと考えています。
<button class="btn -primary">
<button class="btn -secondary">
.btn {
font-size: 20px;
background-color: grey;
&.-primary {
background-color: green;
font-size: 30px;
padding: 10px;
}
&.-secondary {
background-color: blue;
}
}
おまけ(状態を表すもの)
サーバー側もしくはJavaScriptによって、何らかの方法で変更された状態をあらわすクラスには接頭辞is-
を付けましょう、と公式には書かれています。
<input class="f-input -type-string is-invalid">
.f-input {
&.is-invalid {
color: red;
border: 1px solid red;
}
}
SMACCSの考えが取り入れられているのかもしれませんが、これも個人的にはis-
を付けるメリットがあまり感じられず、そのルールを覚える学習コストの方が上回るため、他のModiferと同じ扱いにしても良いのでは?と考えています。
おわりに
CSSを取り巻く設計手法はBEMの他にも色々と存在しますが、公式の形にとらわれずに、自分たちにとって都合の良いように取り入れて、上手く運用できればそれで良いのではないかと思います。
にしても、CSSはグローバル汚染問題やセレクタの命名が辛い。。
出来ることなら、コンポーネント指向のSPAでCSS in JSしたいです。