32
28

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 1 year has passed since last update.

LinkbalAdvent Calendar 2018

Day 6

BEMよりスタイリングが快適な独自のCSS設計(命名規則)の紹介

Last updated at Posted at 2018-12-06

この命名規則は、少しBEMに似ていますが、単にBEMの設計をカスタマイズしたものではありません。

一番の特長は、Class名とHTML構造をシンクロさせることで、CSSからHTML構造を予測できるという点で、この特長によってスタイリング(CSSをあてる作業)が非常に快適になっています。

(後述の特長:2で紹介)

※ BEM(特にMindBEMding)との比較を軸に紹介していきたいと思います。

完成形

.Parent {}
.Parent-child {}
.Parent-child-grandChild {}
.Parent-child-grandChild.modifier {}
HTMLの例
<ul class="UserList">
  <li class="UserList-item">
    <div class="UserList-item-name">name</div>
    <div class="UserList-item-desc">desc</div>
  </li>
  <li class="UserList-item modifier">
    <!-- ... -->
  </li>
</ul>

特長

特長1: 記法

  • 登場する記号は一つのみで、**親子関係を表すために-(ハイフン)**を使います
  • 複数語は記号を使わずにキャメルケースで書きます

.ParentName-childName

block-name__element-name--modifierのようにたくさんの記号が登場するMindBEMdingと比べてかなりシンプルなので、見てすぐに理解できます。

記号はプロジェクト内で統一されていれば、好きなものに置き換えられます。

特長2: 「Block->Element」ではなく「Parent->Child->GrandChild->..」

これが最大の特長となります。

パーツ単位で実装していく考えについてはBEMと同じです。

BEMと大きく異なる点は、「子孫はHTMLの構造通りにネスト」していくということです。

BEM 本規則
.block .Block
.block__element .Parent-child
.block__element .Parent-child-grandChild

BEMはBlockの直下に全ての子孫(Element)が属しますが、この規則は子は親の下に、孫は子の下に属すような命名をします。

<div class="Parent">
  <div class="Parent-child">
    <div class="Parent-child-grandChild"></div>
  </div>
</div>

これの何が嬉しいのかというと、まずは下記の2つのCSSを見比べてください。

BEM
.block {
  &__elementA {}
  &__elementB {}
  &__elementC {}
}
.Parent {
  &-childA {
    &-childB {}
    &-childC {}
  }
}

この規則(後者)では、「BCを横に並べたいなら、Adisplay: flex;をつければよい」ということがすぐに分かります。
他にも、「Acolor: #AAAをつけるとBCの文字色にも影響する」ということがすぐに分かります。

一方BEMでは、実際のHTML構造と照らし合わせなければそれが分かりません。

CSSでのスタイリングの多くは、レイアウト系・装飾系、いずれも親子関係を意識しなければいけないものがほとんどなので、この特長はとても便利に働きます。

上記は、「Class名がHTML構造を再現している」という前提のもと成立していますので、このルールは確実に守られなければいけません。

子孫の世代数

子孫の世代数は3つまでを推奨します。

子孫が増えれば名前が長くなってしまうという問題もありますが、
それ以前に、子孫が多すぎる場合は必要以上のタグでラッピングしているか、パーツ化の粒度が大きすぎる可能性があります。

パーツ化の粒度が大きすぎると、親子関係が硬化し、パーツの移動や再利用の際に不便になります。

この制限の重要度はそれほど高くないため、もし面倒であれば省略してもよいと思います。

特長3: Modifierはマルチクラス

Modifierはマルチクラスを使います。

.SubmitButton {}
.SubmitButton.large {}
.SubmitButton.blue {}
<div class="SubmitButton large blue">Button</div>

BEM(↓)に比べ短く読み取りやすいです。

<!-- BEM -->
<div class="SubmitButton SubmitButton--large SubmitButton--blue">Button</div>

Parentがパスカルケースである理由は、このModifierとの混同を避けるためです。

Modifier単体にグローバルなスタイルを当てることは避けてください

.bold という、それ単独でfont-weight: bold;を持つ汎用的なModifierを作ったとします。
目先は便利に働くかもしれませんが、ある箇所では文字の太さではなく、border-width: 1px;border-width: 2px;にするためにこの名前を使いたいかもしれません。

実装規模が大きくなると、グローバルなスタイルはそのように邪魔な存在となります。


ここまでが特長の紹介です。

デメリット: 有名でない

当たり前ですが、BEMやSMACSSのように多くの人が書いてきたルールではありません。

オレオレ設計やフレームワーク全てに言える問題ですが、複数人のプロジェクトで使いたい場合、これを採用することに納得してもらったり、ルールを覚えてもらったりする必要があります。

おわりに

自分は基本的に、(多少気に入らないものでも)人気なものや流行っているものをプロジェクトに使うのが無難で、一緒に開発する人のためになると思っています。

しかしCSSに関しては、現在主流になっている設計が最善だと思えず、これまで色々と模索してきました。

この規則については、色々な開発に使ってきて、特に破綻したということもなく好調なため紹介してみました。

詳細なルールと具体例

↓これ以降は上で書いたルールの列挙と、間違った使い方の例ですので、実際に導入する人以外は読む必要はありません。

Rules

  • 親子関係を-を用いて表してください
    • HTMLの親子関係と矛盾しないでください
    • 例:.Parent-child-grandChildはHTMLでも.Parent-childを親に持つ必要があります
    • 例:.Parent-childA.Parent-childBはHTMLでも必ず兄弟関係にある必要があります
  • 親子関係はn世代までです
    • 例:.Parent-foo-bar-bazのように子孫が増えた場合、別のパーツにできないか、そもそもHTML要素を減らすことができないか検討してください
  • 複数語をつなげる場合はlowerCamelCaseを使ってください
    • 例:.Parent_name-child-nameのように複数語の繋ぎに-_を使ってはいけません
  • 部分的に違うスタイルをあてるためのmodifierはマルチクラスにしてください
    • 例:.SubmitButton.large.blueのように複数のmodifierをつけることができます
    • 例:.large { font-size: 20px; }のように、modifier単体にスタイルをあてないでください

間違った例

この規則が、単なるBEMの記号違いだと認識されてしまうと、以下のような間違いを生みます。

<ul class="UserList">
  <li class="UserList-item">
    <div class="UserList-name">name</div>
    <div class="UserList-desc">desc</div>
  </li>
</ul>

.UserList-name.UserList-itemの子供なので、.UserList-item-nameとしてください。(descも同様)


<ul class="UserList">
  <li>
    <div class="UserList-item-name">name</div>
    <div class="UserList-item-desc">desc</div>
  </li>
</ul>

nameとdescは、.UserList-itemを親に持つ必要があります。
もし<li>に対するスタイルがなくても、必ず.UserList-itemというclass名を付与してください。


<ul class="UserList">
  <li class="UserList-item">
    <a>
      <div class="UserList-item-name">name</div>
      <div class="UserList-item-selfIntroduction">self introduction</div>
    </a>
  </li>
</ul>

.UserList-item-nameの親がaタグになっていますが、.UserList-item-nameの親は.UserList-itemである必要があります。

32
28
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
32
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?