2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BEMでElement__Elementを許容するのを検討する

Last updated at Posted at 2019-05-02

始めに

皆さんはCSSはBEMで書いていますでしょうか?僕は基本的にBEMを使っていて、Elementは1つのみに徹底して書いてきました。ただこの運用にするとあんまりに辛いなと思ってきてElementにElementを書いてもいいんじゃないかと思ってきました。

理想のBEM構成にした時の問題

例えばTODOリストをコーディングするときに、Blockとしてはリストとアイテムは分けておくと柔軟性が良くなるので以下のようにしておくのがベストです。リスト側でアイテム間のマージンを設定しておくと、アイテムだけのパーツは他の場所でも使いまわしやすくなります。

オンラインエディタで書いたものはこちらになります。

See the Pen Element2階層のBEMサンプル by wintyo (@wintyo) on CodePen.

理想のBEM構成
//- リストのBEM
ul.todo-list
  //- アイテムごとのマージンをここで書く)
  li.todo-list__item
    //- アイテムのBEM(ここではマージンをかかない)
    .todo-item
      input.todo-item__check(type="checkbox")
      span.todo-item__text TODO
      button.todo-item__button 削除
  li.todo-list__item
    .todo-item
      input.todo-item__check(type="checkbox")
      span.todo-item__text TODO2
      button.todo-item__button 削除
  li.todo-list__item
    .todo-item
      input.todo-item__check(type="checkbox")
      span.todo-item__text TODO3
      button.todo-item__button 削除
// TODOリストのリスト部分のみ
.todo-list {
  padding: 0;
  
  &__item {
    & + & {
      margin-top: 10px;
    }
  }
}

// TODOリストの中身のみ
.todo-item {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 10px;
  border: solid 1px #ddd;
  border-radius: 5px;
  
  &__text {
    flex: 1 1 0;
    padding: 0 5px;
  }
}

ただこの運用は明らかに冗長で、まとめてひとつのBlockにしたいときもあります。その場合、以下のように書いてしまうことがあります。

形式だけElement一つにする
ul.todo-list
  li.todo-list__item
    //- アイテムElementの後ろに名前を足して配下感を出す
    input.todo-list__item-check(type="checkbox")
    span.todo-list__item-text TODO
    button.todo-list__item-button 削除
  li.todo-list__item
    input.todo-list__item-check(type="checkbox")
    span.todo-list__item-text TODO2
    button.todo-list__item-button 削除
  li.todo-list__item
    input.todo-list__item-check(type="checkbox")
    span.todo-list__item-text TODO3
    button.todo-list__item-button 削除
.todo-list {
  padding: 0;
  
  &__item {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 10px;
    border: solid 1px #ddd;
    border-radius: 5px;

    & + & {
      margin-top: 10px;
    }

    // itemエレメント以下で使っている感じを出す
    &-text {
      flex: 1 1 0;
      padding: 0 5px;
    }
  }
}

一応SCSSの階層関係を見るとElementの下に更に書かれそうだなという雰囲気は出てますが、単純に単語を連結したいのかの判断が難しくなります。

Elementの中にElementを書くのを許容して明記させる

これを書くくらいだったらもう__をもう一つ増やしてElementの下に更にElementをはやしていることが分かるようにした方がいいかなと思いました。3つは流石にキツいのでブロックを分けましょう。

Elementの中にElementを書く
ul.todo-list
  li.todo-list__item
    //- アイテムElementの下で使うクラス名だと一目瞭然(もし違った書き方をしていたら指摘しやすい)
    input.todo-list__item__check(type="checkbox")
    span.todo-list__item__text TODO
    button.todo-list__item__button 削除
  li.todo-list__item
    input.todo-list__item__check(type="checkbox")
    span.todo-list__item__text TODO2
    button.todo-list__item__button 削除
  li.todo-list__item
    input.todo-list__item__check(type="checkbox")
    span.todo-list__item__text TODO3
    button.todo-list__item__button 削除

.todo-list {
  padding: 0;
  
  &__item {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 10px;
    border: solid 1px #ddd;
    border-radius: 5px;

    & + & {
      margin-top: 10px;
    }

    // itemエレメント以下で使う設定
    &__text {
      flex: 1 1 0;
      padding: 0 5px;
    }
  }
}

終わりに

真面目にBEMで書いていくと、すぐにブロックを分ける必要がありました。Vue.jsとかだと同一ファイルに何個もブロックを書いても問題ありませんが、単純な静的サイトでscssファイルに書く場合はクラス名とファイル名は一緒になっていないと探しづらかったりするのでブロックの安易な分割は結構辛いなと思っていました。なるべくブロックを分割せずに上手くまとめようとすると謎のHTML構成になってしまい、修正が難しくなってしまうことも多々ありました。
そこで2階層まではBlock__Element__Elementで書けるようにして1つのブロックにまとめれるようになるともう少し保守がしやすくなるんじゃないかなと思いました。
ただこのようにかくと更に長くなるので、modifierが凄いことになるので、ここはマルチクラスに変えたりするといいのかなと思いました。
BEM + RSCSSでVariant BEMを検討する

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?