BEMを使ったSassファイルの整理

このウェブサイトのSassファイル群はずっとフラットなファイル構成でやっていた。主にSassが相対パスの修正を行うことができないことが理由だったけど、最近はポストプロセスすればどうにでも出来そうな感じなので、あまり気にせず整理することにした。単純にカテゴリ分けするだけでも良いのだけど、BEMを応用してやってみている。

CSSのクラス名及び変数やプレースホルダー・クラスにはまだ手を付けず、まずはBEMツリーとルールセットの配置の対応を作るところから始めた。

以上のようなルール付けの元にやってる(未完成)。

ブロック

scss/
├ _header.scss
└ header/
   ├ _logo.scss
   └ _site-navigation.scss

ファイル名がブロックになり、かつ繰り返しにならないようにディレクトリを使って配置する。CSSのクラス名で.header__site-navigationになるであろうルールセットが含まれるのがheader/_site-navigation.scssになる。必要なら必要なだけネストしていけば良い。例えば.header__site-navigationにナビゲーションのリスト以外に検索ボックスやRSSフィードを表示するブロックがあるなら以下のようにする。

scss/
├ _header.scss
└ header/
   ├ _logo.scss
   ├ _site-navigation.scss
   └ site-navigation/
      ├ _feed.scss
      ├ _list.scss
      └ _searchbox.scss

header/_header.scssあるのはちょっと気持ち悪いし、ブロック単位での一括削除がしづらくなるので、header/_index.scssとかの方が良いのかもしれない。

エレメント

body > header nav {
  ul {
    display: inline-table;
  }

  li {
    display: table-cell;
  }
}

ルールセット内で1段階ネストするとエレメントになる。先述のようにブロックは必ずファイルになるので、&を使わないネストは必ずエレメントとすることができ、読みやすくなる。

ブロックが分散する前提なので、ブロックをまたいだエレメント間でのルールの共有が難しい。そのためプレースホルダー・クラス頼みになるので、見通しがちょっと悪くなる。

モディファイア

body > header nav {
  li {
    &.current {
      border-bottom: 3px double;
    }
  }
}

&を使ってネストさせるとモディファイアになる。ネストでモディファイアでも良さそうだけど、それだとブロックに対するモディファイアが、エレメントと同じになってしまうので混乱する。Sass (に限らないけど)のネストは深くするべきではないので、2段階のネストをモディファイアと確定させると、これ以上のネストがまず起こらないようになる。

出力されるセレクターに無駄が出るのと、&をSass本来の用途として使っていないところが良くない。


BEMの命名規則を使ったクラス名は役に立つとは思うけど、好きではない。ので、ファイル構成を使ってSassのモジュール化を進めてみた。前にちょっと書いたのを実戦投入し始めたみたいな話。