yutaponのブログ

javascript界隈の興味あるネタを備忘録的に残しておく場所

CSSのクラス名を決めるときに抑えておきたいBEMって概念

普段フロントの開発ばかりやってるので、たまにはCSSのネタを。

CSSのidとかclassとかの命名って難しいです。
適当につけてると破綻してくる。

そこでBEMを覚えておくと命名に規則性を持たせることができます。
でも結論からいうと、完全にBEMで作るのは現実的ではないかなと感じてます。
なので、こういう概念があるから参考にして使うってのがいいと思います。

BEMとは?

BEMって何?はこちらの記事がとてもわかりやすかったので参考にしてみてください。
BEM スタートガイド ― これからのWEB フロントエンド開発に必要な方法論に触れてみる | zerokara web


この記事ではBEMっていうと Block, Element, Modifire を意識した
命名規則のことを指すことにします。

たとえば、このブログのタイトル部分のHTMLを例にすると、
現状こうなっているHTMLが

<header id="blog-title" data-brand="hatenablog">
  <div id="blog-title-inner">
    <h1 id="title"><a href="http://yutapon.hatenablog.com/">yutaponのブログ</a></h1>
      <h2 id="blog-description">javascript界隈の興味あるネタを備忘録的に残しておく場所</h2>
  </div>
</header>

↓こうなるみたいです。

<header id="blog-title" data-brand="hatenablog">
  <div id="blog-title__inner">
    <h1 id="blog-title__title"><a href="http://yutapon.hatenablog.com/">yutaponのブログ</a></h1>
      <h2 id="blog-title__description">javascript界隈の興味あるネタを備忘録的に残しておく場所</h2>
  </div>
</header>

元のソースでは単語をハイフンで区切ることで何となく命名してますが、
BEMっぽくしてみた方では命名から明確な意図を読み取れるようになります。

BEMの命名規則

BEMの命名規則はBlock, Element, Modifireの順に単語を並べます。
クラス名を記述する場合は以下のようになります。

.block__element--modifire

Blockの次はアンスコ2つ、Elementの次はハイフン2つで区切り、
最大3つの要素から命名されます。

各要素が何を表すかを簡単に補足しておくと

  • Block
    • 要素の集合
  • Element
    • 具体的な要素
  • Modifire
    • Elementの修飾

といった感じです。

また例を出して設計してみます。
フォームの送信ボタンにスタイルを当てるときにBEMを使ってみると
クラス名はこんな感じに設計できます。

// block
.myform {}

// element
.myform__submit-btn {}

// modifire
.myform__submit-btn--hover {}
.myform__submit-btn--disable {}

クラス名を見ただけで、それがどんな効果を持つのか想像できそうですよね。

BEMの短所

BEMに則って設計するとクラス名がやたら長くなります。
スマホ向けサービスみたいな少しでもファイルサイズを減らそうと頑張ってる
ところでクラス名とかが長いと何か違う気がします。

またググって見つけましたが以下のような問題があるようです。
BEMってどうよ的な流れ。 - Togetterまとめ


BEMの使いどころ

最近は複数のクラスを合わせてスタイルを当てるマルチクラス設計が流行ってます。
BEMはこのマルチクラス設計と相性悪いです(クラス名長くて可読性落ちたりするので)。
こちらの記事でも言及されてますが、シングルクラス設計とBEMは相性が良いみたいです。

BEMという命名規則とSass 3.3の新しい記法 - アインシュタインの電話番号

今どきのフロントエンドの人は生のCSSを書くことはほとんどなくなっていて、
CSSプリプロセッサを使って開発しています。
CSSプリプロセッサのextendとかmixinとか使い倒すことで
柔軟な設計が出来るんじゃないかと感じてます。

マルチクラス設計とシングルクラス設計

マルチクラス設計ってのはこんな感じのやつですが、
(※例が全然セマンティックじゃなくてすみません)

// クラスを2つ指定
<div class="blog-title large"></div>

要は小さい部品を組み合わせて適切なスタイルを当てるって手法です。
シングルクラス設計にもこの手法は適用できます。

// @file example.styl

// mixin
title()
    margin 10px 5px
    padding 0 0 5px
    font-weight bold
    border-bottom 2px solid #000
large()
    font-size 1.5em

#blog-title
    title()
    large()
// @file sample.html

<div id="blog-title"></div>

出力されるCSSはこのようになります。

#blog-title {
  margin: 10px 5px;
  padding: 0 0 5px;
  font-weight: bold;
  border-bottom: 2px solid #000;
  font-size: 1.5em;
}

要は小さい部品を組み合わせる場所をHTML側でするのか、
CSS側でするのかの違いです。

シングルクラス設計だとしても、スタイルを小さい部品としてたくさん用意して
合成して出力してしまえばいいんです。

これってオブジェクト指向言語でいうextendsとかimplementsに似てますね。
こういうのをOOCSS (Object-Oriented CSS) っていいます。
気になったら調べてみましょう。


ちなみに↑の例で、mixinで小さい部品を作ったのは
出力されるCSSのサイズを小さくするためです。
下の例はextendを使った場合です。出力されるCSSがmixinのときより
冗長になっているのがわかります。

// @file sample.styl
.title
    margin 10px 5px
    padding 0 0 5px
    font-weight bold
    border-bottom 2px solid #000
.large
    font-size 1.5em

#blog-title
    @extend .title
    @extend .large
// 出力されるCSS
// @file sample.css
.title,
#blog-title {
  margin: 10px 5px;
  padding: 0 0 5px;
  font-weight: bold;
  border-bottom: 2px solid #000;
}
.large,
#blog-title {
  font-size: 1.5em;
}

 

おわりに

BEMの話してたら脱線してOOCSSになってた。
まとめとしては

  • BEMをそのまま使うのは難しいので概念だけ覚えておく
  • クラス名を付けるときはBlock, Element, Modifireを意識する
    • アンスコ2つ、ハイフン2つの区切りは意図が伝わりやすいけど、この文法にこだわる必要はない

です。