block-modifier.sass
=block--($modifier)
$current: &
$block: str_slice("#{&}", 0, str-index("#{&}", "__") - 1)
@at-root #{$block}
&--#{$modifier}
#{$current}
@content
使い方
親のBlockにModifierが指定されている場合のElementの見た目を、Element以下にネストして書ける。
user-icon.sass
.user-icon
&__image
width: 100px
height: 100px
+block--(round)
border-radius: 50px
user-icon.css
.user-icon__image {
width: 100px;
height: 100px;
}
.user-icon--round .user-icon__image {
border-radius: 50px;
}
動機: BlockにModifierを付けたい
HTMLマークアップするときElementにModifierつけると書くのがダルいし横長になる。
.list
%li.list__item.list__item--icebox 海に行く🏊
%li.list__item.list__item--icebox スイカ割る🍉
BlockにModifierつけると横幅減って読みやすい
.list.list--icebox
%li.list__item 海に行く🏊
%li.list__item スイカ割る🍉
BlockのModifierによってElementの見た目を変えるのはしんどい
Sassが書きづらい
参考: BEMでmodifierを作る時に便利な&の変数化パターン
.list
$self: &
&__item
// デフォルトの項目の見た目
&--icebox
#{$self}__item
// iceboxに入っている項目の見た目
一方Elementにmodifierをつけるとこんな感じ。
.list
&__item
// デフォルトの項目の見た目
&--icebox
// iceboxに入っている項目の見た目
Blockのmodifierによって見た目を変えたいElementが他にもある場合、BlockのModifierでまとめようとするとこんな感じになってElementの定義と離れてしまう
.list
$self: &
&__item
// デフォルトの項目の見た目
&__foo
// デフォルトのfooの見た目
&__bar
// デフォルトのbarの見た目
&__fizzbuzz
// デフォルトのfizz buzzの見た目
&--icebox
#{$self}__item
// iceboxに入っている項目の見た目
#{$self}__foo
// iceboxに入っているfooの見た目
#{$self}__bar
// iceboxに入っているbarの見た目
#{$self}__fizzbuzz
// iceboxに入っているfizz buzzの見た目
それぞれのElementの下に書くと縦に伸びるし凸凹感がすごい
.list
$self: &
&__item
// デフォルトの項目の見た目
&--icebox
#{$self}__item
// iceboxに入っている項目の見た目
&__foo
// デフォルトのfooの見た目
&--icebox
#{$self}__foo
// iceboxに入っているfooの見た目
&__bar
// デフォルトのbarの見た目
&--icebox
#{$self}__bar
// iceboxに入っているbarの見た目
&__fizzbuzz
// デフォルトのfizz buzzの見た目
&--icebox
#{$self}__fizzbuzz
// iceboxに入っているfizz buzzの見た目
mixinを使うと便利
block-modifier.sass
=block--($modifier)
$current: &
$block: str_slice("#{&}", 0, str-index("#{&}", "__") - 1)
@at-root #{$block}
&--#{$modifier}
#{$current}
@content
このmixinを使うとこのSassが
.list
$self: &;
&__item
// デフォルトの項目の見た目
&--icebox
#{$self}__item
// iceboxに入っている項目の見た目
こうなる
.list
&__item
// デフォルトの項目の見た目
+block--(icebox)
// iceboxに入っている項目の見た目
このSassが
.list
$self: &
&__item
// デフォルトの項目の見た目
&__foo
// デフォルトのfooの見た目
&__bar
// デフォルトのbarの見た目
&__fizzbuzz
// デフォルトのfizz buzzの見た目
&--icebox
#{$self}__item
// iceboxに入っている項目の見た目
#{$self}__foo
// iceboxに入っているfooの見た目
#{$self}__bar
// iceboxに入っているbarの見た目
#{$self}__fizzbuzz
// iceboxに入っているfizz buzzの見た目
こう
.list
&__item
// デフォルトの項目の見た目
+block--(icebox)
// iceboxに入っている項目の見た目
&__foo
// デフォルトのfooの見た目
+block--(icebox)
// iceboxに入っているfooの見た目
&__bar
// デフォルトのbarの見た目
+block--(icebox)
// iceboxに入っているbarの見た目
&__fizzbuzz
// デフォルトのfizzbuzzの見た目
+block--(icebox)
// iceboxに入っているfizz buzzの見た目
まとめ
SassとBEMべんり
もう少し汎用的にするとこういう感じです。
within-block.sass
=within-block($s)
$current: &
$block: str_slice("#{&}", 0, str-index("#{&}", "__") - 1)
@at-root #{$block}#{$s} &
@content
.user-icon
&__image
width: 100px
height: 100px
+within-block(--round)
border-radius: 50px
+within-block(".is-round")
border-radius: 50px