LoginSignup
5
1

More than 5 years have passed since last update.

Element Modifierと同じノリでElementの見た目を変えれるBlock ModifierのSassの書き方

Last updated at Posted at 2017-05-08
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
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1