吉本式 Web制作のコーディングガイドライン

美しいコーディング・設計をするためのガイドラインコンテンツです。

SCSSのファイル設計(BEM設計からFLOCSS設計に)

昨年(2018年)の5月ごろに、吉本式BEM設計という考え方のガイドラインコンテンツをまとめました。
一部の表現の甘さなどにより予期せぬ方向で話題になってしまいましたが、設計の考え方に関しては、それなりに評価していただけたのかなと思っています。
実は、吉本式BEM設計のガイドラインコンテンツを発信した頃には既に、実務では吉本式BEM設計は採用しておらず、FLOCSS設計の考え方で独自にカスタマイズしたSCSSファイルの設計でやっていました。
誤解のないように補足しておくと、吉本式BEM設計は長年BEM設計をやってきた中でカスタマイズしたものですので、完成度はそれなりに高いと思っており、また美しいファイル設計になっていると自負しています。
その中でFLOCSS設計の考え方に移行した理由は、BEM設計の考え方以外にも実務として経験しておきたいというのも、もちろんありましたが、吉本式BEM設計で唯一違和感のあった(違和感が出てしまった)設計があり、それを改善できないかと検討した結果、考え方をFLOCSS設計ベースにすることで納得のできる設計に改善できた、というのが移行した理由となります。

吉本式BEM設計で唯一違和感のあった(違和感が出てしまった)設計

吉本式BEM設計ではBlockにとなる要素、Elementとなる要素をルール化(固定化)しました。
これは、BEM設計で「この要素はBlock要素か?Element要素か?」という迷いを無くすためです。
全てのコーディング作業において、迷うことが作業速度を遅くする原因です。
迷いなくコーディングすることができれば、コーディング速度が早くなります。
では、どうすれば迷いがなくなるか、それはルール化することです、さらに言うと例外を持たせないルール化(ルールの厳格化)です。
例外を持たせてしまうと、そこに迷いが生まれてしまいます。
このルール化を定めたものが吉本式BEM設計になるのですが、ルール化したことで違和感が出てしまいました。
私個人的には、吉本式BEM設計で出てしまった違和感は1つです。(他の人が試すとたくさん出てきてしまうかもしれませんが・・・というのは補足しておきます。)

その唯一出てしまった違和感というのは、「同じ装飾(デザイン)の要素なのにクラス名が異なってしまう。」ということです。
例を挙げてみます。

html
<section class="blockA">
<h2 class="blockA_heading">BLOCK-Aの見出しです。</h2>
・・・(省略)
</section>

<section class="blockB">
<h2 class="blockB_heading">BLOCK-Bの見出しです。</h2>
・・・(省略)
</section>

blockAのsection要素とblockBのsection要素のコンテンツ内容は全く異なるという前提で、見出しのみ同じ装飾(デザイン)だと仮定します。
吉本式BEM設計には、見出し(h2要素)は必ずElementにするというルールがあるため、親のBlock要素に依存するクラス名になり、それぞれの見出しのクラス名はblockA_headingblockB_headingになります。
この辺の詳しい考え方は吉本式BEM設計をしっかり読んでいただければ、ご理解いただけると思います。

同じ装飾(デザイン)で異なるクラス名の要素が生まれてしまいますが、実装ではmixinを使用してスタイルをあてるため、重複して同じスタイルシートを記述することはありません。
ただ、「同じ装飾(デザイン)の要素なのにクラス名が異なってしまう。」という違和感を改善したい。
理想的なマークアップとしては明確で、次のようになります。

html
<section class="blockA">
<h2 class="heading">BLOCK-Aの見出しです。</h2>
・・・(省略)
</section>

<section class="blockB">
<h2 class="heading">BLOCK-Bの見出しです。</h2>
・・・(省略)
</section>

これは皆さんが「でしょうね」と納得するところだと思います。
同じ装飾(デザイン)なのだから、同じクラス名(heading)でしょうね。

これを吉本式BEM設計で取り入れてしまうと、ルールが崩れてしまいます。
見出しがElementではなく、Blockであるなら、画像もBlockでよくない?テキストもボタンもリストもBlockでよくない?
こうなってしまいます。

もちろんBEM設計の考え方の解釈は自由ですので、BEM設計で見出し、画像、テキスト・・・をBlockとして設計するのは問題ありません。
ルールを厳格化した吉本式BEM設計では、難しかったのです。

BlockとElementではなく、ProjectとComponentという考え方

BEM設計のElementは、Blockに依存します。
そのため、Element単体で使用することができません。
FLOCSS設計の場合、再利用できる最小の単位のモジュールをComponentとし、ProjectはいくつかのComponentと、Elementで構成されています。
ComponentとBlockを置き換えると、BEM設計のBlockと同様な考え方です。
このComponentという考え方を取り入れることで、自分の中で納得できるものを感じました。
(BEM設計においても、Blockという考え方を柔軟にすることで、解決はできます。)

FLOCSSの考え方をカスタマイズする

FLOCSSの考え方の説明は割愛しますが、FLOCSSの考え方を理解していないと、ここからの解説は理解できないかもしれません。
自分なりにカスタマイズする前に、FLOCSS設計を実務レベルで何度か実践しました。
その中で、吉本式BEM設計の考え方をFLOCSS設計にどう組み込むかを検討し、いくつかカスタマイズするポイントをリストアップしました。

・基本構成
・ディレクトリ構成
・クラス名の命名規則

大きく分けて上の3つのポイントです。

基本構成について

FLOCSSの基本構成は、Foundation、Layout、Objectになります。

Foundation
プロジェクトにおける基本的なスタイルを定義します。
具体的なscssファイルでいうと、base.scss、reset.scssが該当します。

base.scss → プロジェクトの基本スタイル
reset.scss → 初期化スタイル

Foundationにこの2つのファイル以外に必要になるケースはないので、ルールとして確定して問題ないと思っています。

Layout
サイト共通となるBlock定義
ヘッダー、フッター、メインコンテンツ、サイドナビなどがこれに該当します。

Object
FLOCSS設計では、このObjectをさらにComponent、Project、Utilityの3つに分類していますが、Component、Projectのみとします。
Utilityを廃止した理由として、Utilityとは便利クラスという位置付けのため、これを利用してしまうと、吉本式で重要としているルールの厳格化から外れてしまいます。

基本構成に関しては、ObjectのUtilityの廃止以外は、そのまま考え方を取り入れさせてもらいます。

ディレクトリ構成について

FLOCSSの考え方では、基本構成通りにディレクトリを構成します。

  • scss
    • foundation
      • xxx.scss
    • layout
      • xxx.scss
    • object
      • component
        • xxx.scss
      • project
        • xxx.scss
      • utility
        • xxx.scss

吉本式では、ここから次のようにカスタマイズしました。

・ObjectのUtilityは廃止したので、utilityディレクトリの削除
・objectディレクトリを廃止し、componentディレクトリ、projectディレクトリを1階層あげる

  • scss
    • foundation
      • xxx.scss
    • layout
      • xxx.scss
    • component
      • xxx.scss
    • project
      • xxx.scss

objectディレクトリを廃止した理由は、単純にこのディレクトリはなくても設計上困らないためです。
このディレクトリ構成に、吉本式BEM設計で使用していたmixinディレクトリ、settingディレクトリを加えます。

mixinディレクトリ → mixinが定義されているscssファイルを格納するディレクトリです。
settingディレクトリ → 初期設定で必要なパラメータなどが定義されているscssファイルを格納するディレクトリです。

基本的にはこのディレクトリになりますが、これらのディレクトリに定義されたファイルはインクルードされるscssファイルになりますので、これらをインクルードする大元のscssファイルが存在します。
また、インクルードされるscssファイル名の頭文字に"_"を入れる必要がありますので、次のようになります。

  • scss
    • foundation
      • _xxx.scss
    • layout
      • _xxx.scss
    • component
      • _xxx.scss
    • project
      • _xxx.scss
    • mixin
      • _xxx.scss
    • setting
      • _xxx.scss
    • style.scss

インクルードされるscssファイル名の頭文字に"_"を入れる必要がある理由に関しては、以前解説したwebpackの設定についての記事で確認してください。
style.scssが全ての定義ファイルをインクルードして、style.cssに出力されますので、次のようなファイルになります。

style.scss
@import './setting/xxx';
@import './mixin/xxx';
@import './foundation/xxx';
@import './layout/xxx';
@import './component/xxx';
@import './project/xxx';

1ページもののLP案件などはこのディレクトリ構成で問題ありませんが、コーポレートサイトやメディアサイトなどの複数ページ案件の場合、考えられるCSS設計は大きく分けて次の2つになります。

・全ページ分のスタイル設定を1ファイルにまとめる
・サイト共通で使用するスタイルとページ単体で使用するスタイルを分ける

前者の「全ページ分のスタイル設定を1ファイルにまとめる」という設計であれば、上記のディレクトリ構成のままで問題ありません。
componentディレクトリ、projectディレクトリにscssファイルが増えていく設計になります。

後者の「サイト共通で使用するスタイルとページ単体で使用するスタイルを分ける」という設計で考えた場合、さらに2通りの設計が考えられます。
ページ単体で使用するスタイルのproject定義のscssファイルをどういうディレクトリ構成にするか。
まずは、ページ単体でスタイルを分けるので、ページごとに出力するscssファイルが必要になります。
pageというディレクトリを作り、そこに各ページのディレクトリを掘り、style.scssを作成します。

  • scss
    • foundation
      • _xxx.scss
    • layout
      • _xxx.scss
    • component
      • _xxx.scss
    • project
      • _xxx.scss
    • mixin
      • _xxx.scss
    • setting
      • _xxx.scss
    • page
      • home
        • style.scss → TOPページ用のスタイル定義
      • about
        • style.scss → ABOUTページ用のスタイル定義
    • style.scss → サイト共通のスタイルを定義するscssファイル

/scss/page/home/style.scss → /css/page/home/style.css
/scss/page/about/style.scss → /css/page/about/style.css

上のようにそれぞれcssファイルが出力されます。
それではそれぞれのページにのみ必要になるproject定義のscssファイルをどのようなディレクトリ構成にするか。

  • scss
    • foundation
      • _xxx.scss
    • layout
      • _xxx.scss
    • component
      • _xxx.scss
    • project
      • _xxx.scss
    • mixin
      • _xxx.scss
    • setting
      • _xxx.scss
    • page
      • home
        • style.scss → TOPページ用のスタイル定義
        • project
          • _xxx.scss
      • about
        • style.scss → ABOUTページ用のスタイル定義
        • project
          • _xxx.scss
    • style.scss → サイト共通のスタイルを定義するscssファイル

それぞれのページのディレクトリ内にprojectディレクトリを作成し、scssファイルを格納する考え方が1つ目です。

  • scss
    • foundation
      • _xxx.scss
    • layout
      • _xxx.scss
    • component
      • _xxx.scss
    • project
      • _xxx.scss
      • home → TOPページ用のproject定義ディレクトリ
        • _xxx.scss
      • about → ABOUTページ用のproject定義ディレクトリ
        • _xxx.scss
    • mixin
      • _xxx.scss
    • setting
      • _xxx.scss
    • page
      • home
        • style.scss → TOPページ用のスタイル定義
      • about
        • style.scss → ABOUTページ用のスタイル定義
    • style.scss → サイト共通のスタイルを定義するscssファイル

projectディレクトリの中に、各ページのディレクトリを作成し、その中にscssファイルを作成すると言う考え方が2つ目。
この2つの考え方が出てきますが、私は1つ目を実務で採用しています。

component定義ファイルに関しては、各ページごとには必要ありません。
componentの定義を具体的に挙げると、見出し、画像、リスト、ボタン・・・という最小単位の要素の定義になり、heading.scss、pic.scss、list.scss、btn.scssと言ったファイル名になります。
これらについては後ほど詳しく解説しますが、あるページにのみ出てくる「見出し」があったとしても、scssディレクトリ直下にあるcomponentディレクトリ内に作成したheading.scssにその「見出し」のスタイルを定義することで問題ありませんので、そのページ用のcomponentディレクトリを作る必要はありません。
下記に私が実際に担当した案件のSCSS設計(一部省略)を公開します。

  • scss
    • foundation
      • _base.scss
      • _reset.scss
    • layout
      • _header.scss
      • _main.scss
      • _footer.scss
    • component
      • _btn.scss
      • _heading.scss
      • _figure.scss
      • _link.scss
      • _tab.scss
      • ・・・省略
    • project
      • _pager.scss
      • _item.scss
      • _breadcrumbs.scss
      • _gnavi.scss
      • _fnavi.scss
      • ・・・省略
    • mixin
      • _animate.scss
      • _font.scss
      • _mq.scss
      • _hover.scss
      • ・・・省略
    • setting
      • _config.scss
      • _function.scss
      • _imports.scss
    • page
      • home
        • project
          • _feature.scss
          • _message.scss
          • _kv.scss
          • ・・・省略
        • style.scss
      • news
        • project
          • _archive.scss
          • _sec.scss
        • style.scss
      • faq
        • project
          • _faq.scss
          • _sec.scss
        • style.scss
      • labo
        • project
          • _flow.scss
          • _sec.scss
        • style.scss
      • ・・・省略
    • style.scss

基本構成、ディレクトリ構成の解説で長くなりましたので、クラス名の命名規則に関しては、次の記事で解説します。