Sass で BEM 的なことをしているときに子要素を他のセレクターの下に潜り込ませたい
ふとしです。
BEM の階層が深い要素を、他で定義した要素の下に潜り込ませたいという話です。
まず解決法は以下です。@at-root
で BEM 用のネストを外しつつ、引数として BEM 用のセレクターを取って潜り込ませます。
@mixin form_control_plus($selector)
@at-root
input[type="text"].form-control
&#{$selector}
@content
.main-content
&__main-list
&__item
@include form_control_plus(#{&}__big-fat-control)
height: 100px
input[type="text"].form-control.main-content__main-list__item__big-fat-control {
height: 100px;
}
そんなわけで後は日記です。
Sass で BEM 的
以下のような感じで定義して
.main-content
&__main-list
margin: 0
&__item
color: #fff
以下のような CSS を得るみたいなやつです。
,main-content__main-list {
margin: 0;
}
.main-content__main-list__item {
color: #fff
}
よくある問題
他でグローバルに定義したセレクターが強すぎて負ける場合があります。
こういうことをしていると
input[type="text"].form-control
height: 40px;
こんな定義をしても
.main-content
&__main-list
margin: 0
&__item
color: #fff
&__big-fat-control
height: 100px
<input type="text" class="form-control main-content__main-list__item__big-fat-control">
height: 40px
が勝ちます。
アドホックに解決
そこで以下のような解決法もありますが、
.main-content
&__main-list
margin: 0
&__item
color: #fff
input[type="text"].form-control
.main-content
&__main-list
&__item
&__big-fat-control
height: 100px
これは二重になる上にめんどくさいので、今回の本題です。
root から定義する mixin を定義する
mixin はセレクターとして使える文字列を引数に取れます。さらに、配下のブロックを @content
として利用できるので、それらを使って強いセレクターの追加セレクターとして定義します。
@mixin form_control_plus($selector)
@at-root
input[type="text"].form-control
&#{$selector}
@content
.main-content
&__main-list
margin: 0
&__item
color: #fff
@include form_control_plus(#{&}__big-fat-control)
height: 100px
これで以下のような CSS が得られるので、height: 100px
が有効になりました。
input[type="text"].form-control.main-content__main-list__item__big-fat-control {
height: 100px;
}