CSS設計の手法を調べると、ITCSSとFLOCSSという2つの名前に行き当たります。どちらも「CSSを秩序立てて管理する」ための考え方ですが、性質が少し違います。前回の記事で触れた :is() / :where() による詳細度設計は、実はこの2つの考え方をベースに、自分のプロジェクト用にハイブリッドした結果でした。この記事では、ITCSSとFLOCSSをそれぞれ整理したうえで、実際にどう組み合わせて運用しているかを紹介します。


    ITCSS(Inverted Triangle CSS)とは

    ITCSSは「逆三角形」を描くように、CSSを詳細度と影響範囲が徐々に狭まっていくレイヤーとして読み込む考え方です。ディレクトリ構造というより「CSSの読み込み順序の設計指針」に近いものです。

    settings/     → グローバル変数、設定(出力されない)
    tools/        → ミックスイン、関数(出力されない)
    generic/      → リセット、normalize
    elements/     → HTML要素の基本スタイル(h1, a, pなど)
    objects/      → 装飾を持たない構造パターン(OOCSS的な骨組み)
    components/   → 具体的なUIコンポーネント
    utilities/    → ヘルパークラス(!importantも許容される最上位)

    ポイントは、上から下に向かって詳細度が単調増加していくべきという規律です。これによって「後から書いたCSSなのに、詳細度が低くて勝てない」というカスケードの事故を構造的に防ぎます。逆に言うと、ITCSSはこの規律さえ守れば、ファイルやフォルダの命名規則自体には強いこだわりがありません。

    ITCSSの逆三角形図 settingsからutilitiesに向かって帯が細くなり、詳細度が単調増加していくITCSSの7層構造を逆三角形で表現した図 詳細度: 低 詳細度: 高 settings variables, tokens tools mixins, functions generic reset, normalize elements h1, a, p objects .l-content components .button, .card utilities .m-1, .d-none

    FLOCSS(Foundation Layout Object CSS)とは

    FLOCSSは、OOCSS・BEM・SMACSSのいいとこ取りをした、日本発のCSS設計手法です。ITCSSが「詳細度の順序」という抽象的な指針なのに対して、FLOCSSはディレクトリ構造と命名規則まで含めた、より実装寄りの仕様になっています。

    foundation/   → reset・base(リセット・ベースの下地)
    layout/       → header・footer・containerなど配置のみ(l-)
    object/
    component/  → 再利用可能な最小パーツ(c-)
    project/    → componentの集合・大きなブロック(p-)
    utility/    → margin/padding/表示切替などの単機能クラス(u-)

    命名はフォルダの頭文字をそのままプレフィックスにし(l- c- p- u-)、Element/ModifierはBEM(MindBEMding)で管理します。ComponentとProjectの境目は「裸の人間がComponent、ネクタイや靴下を着てビジネスマンになったらProject」という比喩がわかりやすく、Componentが複数集まって意味を持つ単位やセクション規模のブロックはProjectに分類します。

    FLOCSSの入れ子構造図 FLOCSSのfoundation、layout、objectの3層と、object配下のcomponent、project、utilityの入れ子構造を示す図 foundation reset・base _base.scss layout 配置のみ _header.scss object component _button.scss project _header.scss utility _color.scss

    2つを並べると見えてくること

    ITCSSとFLOCSSを並べると、実はかなり対応関係があります。

    ITCSSFLOCSS役割
    settings / tools(概念なし)変数・mixin
    generic / elementsfoundationリセット・下地
    objectslayout配置のための骨組み
    componentsobject/component, object/projectUIパーツ
    utilitiesobject/utility単機能クラス

    FLOCSSの object ディレクトリは、ITCSSでいう「objects〜components」のレンジを component / project の2段階に割って実装可能な粒度に落とし込んだもの、と捉えると理解しやすくなります。


    詰まったポイント:色トークン系ファイルの置き場

    実際に手を動かしてみて最初に迷ったのが、style-color-palette1.scss のような色のバリエーションを大量に定義したファイルの置き場でした。

    このファイルがやっていることは、

    • カラーパレットというデザイントークンに近い性質を持つ(settingsっぽい)
    • 実際には .is-white .is-black のようなクラスとして出力される(componentやutilityっぽい)
    • 特定のコンポーネントに紐づくわけではなく、ボタンにもバッジにもボックスにも使われる横断的なもの(utilityっぽい)

    という、3つの性質が混ざった状態でした。FLOCSSの object/component に置くにはコンポーネント単体に紐づかなすぎるし、object/utility に置くには「色」という装飾的な性質がOOCSS的な「構造と装飾の分離」という原則と少し噛み合わない。SMACSSの「Theme」カテゴリに寄せる手もありますが、FLOCSSにはThemeという概念自体が存在しません。

    結局、このファイルは「コンポーネント側の --c-* カスタムプロパティに値を流し込む役割」と割り切り、ITCSSでいう components のレンジ(詳細度2〜3)に置くことで決着しました。「見た目のクラスを出力するが、コンポーネント自体は定義しない」というファイルは、置き場所に迷ったらコンポーネント側の詳細度レンジに合わせる、というのが今回得た経験則です。


    たどり着いた6層構成

    ITCSSの詳細度の規律と、FLOCSSのobject三分割の実装しやすさを両方取り入れて、最終的に次の6層構成に落ち着きました。

    レイヤープレフィックス役割詳細度の目安
    settings(なし)変数・トークン・mixin。CSSの実指定なし
    foundations.fd-*リセット・下地(reset → settings → elements → primers)0〜1
    layouts.ly-*ページ構造(body > page > section > container > wrapper > item)1〜2
    components.cm-*ボタン・バッジ・カードなどのUIパーツ2〜3
    utilities.ut-*margin・displayなど単機能クラス3〜4
    trumps(なし)緊急時の上書き。!importantを許容

    settings は本来ITCSSの独立レイヤーですが、「実体を持たない(CSSを出力しない)」という性質上、ファイルの読み込み順序的に foundations の直前に置いておくと管理しやすいため、実運用上は foundations に含めて扱っています。

    詳細度のレンジは、前回の記事で紹介した :is() / :where() の組み合わせで実セレクタとして固定しています。

    /* components層: .theme-name + :is()内最大値 = 詳細度(0,2,0) */
    .theme-name :is(.badge, .button) { /* 基本形 */ }
    .theme-name :is(.badge, .button):where(.is-narrow) { /* バリアントは:where()で増やさない */ }
    
    /* utilities層: .theme-name + :not([unutility]) + :is() = 詳細度(0,3,0) */
    .theme-name:not([unutility]) :is(.m-1r, .m-1r_sp) { margin: calc(var(--⅝fem) * 1); }

    utilities層に付けている :not([unutility]) は、単に詳細度を1段階稼ぐためだけでなく、unutility という属性を要素に付与するだけでユーティリティクラス全体を一括無効化できる「エスケープハッチ」としても機能しています。FLOCSSにはこうした「ユーティリティそのものを止める」仕組みは標準で用意されていないので、独自に追加した部分です。

    CSS詳細度を図解する:IDs・class・typeから :is() :where()まで CSSが「思った通りに上書きされない」とき、原因の多くは詳細度(specificity)の理解不足です。前回までの記事で :is() / :where() を使った詳細度設計の話をしてきましたが、そもそも詳細度がどう計算されるのかを整理していなかったので、今回...  続きを読む

    ITCSS・FLOCSSをそのまま使わなかった理由

    最後に、なぜ素直にITCSSやFLOCSSをそのまま採用しなかったのかを整理しておきます。

    • ITCSSをそのまま使わなかった理由な詳細度の規律としては優れているが、ディレクトリ構造や命名規則の指針がないため、複数人での運用や命名の一貫性を担保しづらい
    • FLOCSSをそのまま使わなかった理由な実装の指針としては優れているが、Layout層とComponent層の詳細度の差が前提として明示されておらず、:is() / :where() のような詳細度制御の仕組みと組み合わせる発想が元々の仕様には含まれていない

    ITCSSの「詳細度は逆三角形で単調増加すべき」という規律をFLOCSSの実装構造に持ち込み、それを :is() / :where() というモダンCSSのセレクタ関数で物理的に強制する、というのが今回たどり着いた形です。

    次の記事では、この :is() / :where() をはじめとした擬似クラス関数が、それぞれ詳細度にどう影響するのかを図解付きで整理します。:not() :has() も含めた一覧表があると、今回の記事で出てきた詳細度の数字の根拠がより追いやすくなるはずです。


    関連記事

    CSS詳細度を図解する:IDs・class・typeから :is() :where()まで CSSが「思った通りに上書きされない」とき、原因の多くは詳細度(specificity)の理解不足です。前回までの記事で :is() / :where() を使った詳細度設計の話をしてきましたが、そもそも詳細度がどう計算されるのかを整理していなかったので、今回...  続きを読む CSSで「何番目か」を指定する:nth系セレクタとクラスベース位置選択の完全ガイド :nth-of-type・:nth-last-of-type の式の読み方から、:is() / :not() / :has() を使ったクラスベース位置選択まで網羅。「最初と最後以外」の複数の書き方と詳細度の比較も収録。CSS設計の実務に役立つリファレンス  続きを読む CSS Layersの使い方と注意点 - 実際に使って分かった問題点 CSS Layersは詳細度問題を解決する強力な仕組みですが、プラグインCSSとの共存に大きな壁があります。実プロジェクトで直面した問題点と、:is() / :where() を使った詳細度設計という代替アプローチを実例つきで解説します。  続きを読む