Edited at

少し細かいBEMい話

More than 3 years have passed since last update.


BEMってむずかしい?

2014年はたくさんのサイトでBEM 、もといBEMな命名規則が採用されたのではないかとおもってます。(拙著でも取り上げてます。)

しかし、実際に導入されているサイトのコードをみてみると、んー、と感じることがあったり、または周りの開発者が、BEMむずかしい、といってるのを聞くことがある。


「これで合ってるの?」

むずかしい、と感じるのはたぶんBlockElementとの関係やバランス、あとはクッソ名前が長くなってしまうことの不安にあるのではないかと考えてます。

例えば、ふとこのQiitaの記事ページのサイドバーにある、関連投稿モジュールをみてみましょう。

関連投稿

これをどうマークアップするか、どういうセレクタを書くかっていうのは人やプロジェクトによって全然違うし、このパターンがQiitaの中でどのくらい・どのように存在するかで変わります。

ただBEMを意識しはじめたことだと、次のように書くかもしれません。すごい極端な例。

<div class="widget">

<h3 class="widget__title">関連投稿</h3>
<ul class="widget__list">
<li class="widget__list__item">
<a href="#author" class="widget__list__item__author">
<img src="author.png" alt="auhtor" class="widget__list__item__author__avatar">
</a>
<a href="#post" class="widget__list__item__title">
記事のタイトル
</a>
</li>
<li class="widget__list__item">
...
</li>
</ul>
</div>

かなり簡素化したHTMLですけど、このWidgetモジュールを構成するツリーをそのままBEMっぽいツリーにしようとすると、こう考えてしまう人はいるかもしれません。

これに対し、次の2点を考えます。


  • ElementのElementは冗長になっている

  • モジュールとしての単位が大きすぎる


モジュールを分解する

先ほどのHTMLに手を加えるならば、僕の場合はこうするだろうってのは次のような形です。

(しれっとちょっとdivは追加してる)

<div class="widget">

<h3 class="widget__title">関連投稿</h3>
<ul class="list">
<li class="list__item">
<div class="media">
<a href="#author" class="media__image avatar">
<img src="author.png" alt="auhtor">
</a>
<a href="#post" class="media__body">
記事のタイトル
</a>
</div>
</li>
<li class="list__item">
...
</li>
</ul>
</div>


  • widget

  • list

  • media

  • avatar

ちょっと細かめに割っていますが、パターンが増えてくる・見えてくると、こういった形になるのではないかと思います。実際にはもっと複雑で、ユニークなデザインが来るので、こんなにすっきりした形にはならないことも多いですが、設計イメージはこんな感じです。


分解できないとすれば?

前述のとおり、分解したって再利用も無いなーみたいなことも多く、そうすると下手に分割をしてもあまり意味ないこともあります。しかし、その場合にもElement__Elementみたいな命名にはならないようにします。

今度も元のHTMLのいじるならこう。

<div class="widget">

<h3 class="widget__title">関連投稿</h3>
<ul class="widget__list">
<li class="widget__listItem">
<a href="#author" class="widget__listItemAuthor">
<img src="author.png" alt="auhtor" class="widget__listItemAvatar">
</a>
<a href="#post" class="widget__listItemTitle">
記事のタイトル
</a>
</li>
<li class="widget__listItem">
...
</li>
</ul>
</div>

何が違うかっていうのは、このモジュールのBlockであるwidgetに対するElementの考え方です。

元のHTMLの場合、ツリーを意識しすぎて、どんどんElementにしてしまっていたのですが、改めた方では、ルートであるBlockのwidgetにぶら下がるようにしています。

widget__listItemAvatarこれは、


ウィジェットの、リストの、アイテムの、アバター...


ではなく、


ウィジェットの、リストアイテム内のアバター


って感じです。(わかりづらそう


まとめ

なんでこんなこと書いてみたかというと、CodeGridの@geckotang氏のCSSConfレポートでも報告があったんですが、CSS設計セッションの中で紹介されてたコード例で、

.main-header__nav-list__link {

... same stuff ...
}

ってのがあって、「ありゃ、そんな名前にするの?」とか思ったからです。(CodeGridの記事の中で、おなじような話を@geckotangが書いているので、読める方はぜひ)

解説したコードが別に正解ってわけでもないですが、Element__Elementなパターンに遭遇したら、立ち止まって考えてみてはいかがでしょーか。