FLOCSSで実現する保守性の高いCSS設計ガイド

大規模なWebサイトやアプリケーションのCSS管理で困っていませんか? セレクタの依存関係が複雑になり、新しい機能の追加が怖い…。スタイルの影響範囲が把握できない…。そんな悩みを抱える開発者は少なくありません。

FLOCSSは、これらの課題を解決する日本生まれのCSS設計手法です。レイヤー構造による明確な役割分担と、シンプルな命名規則により、チーム開発でも破綻しにくい設計を実現します。

この記事では、FLOCSSの基本から実践的な活用方法まで、具体的なコード例を交えて解説します。あなたのプロジェクトで、より保守性の高いCSSを書けるようになりましょう。

FLOCSSの基本概念

FLOCSSは「Foundation」「Layout」「Object」という3つの大きなレイヤーでCSSを設計・管理する手法です。

他のCSS設計手法との違い

CSS
/* OOCSS */
.button { }
.button-primary { }

/* BEM */
.button__icon { }
.button--large { }

/* FLOCSS */
.c-button { /* Component */
  /* カスケード層を使用した詳細度制御 */
  @layer component {
    padding: 1rem 2rem;
    border-radius: 0.5rem;
  }
}

.p-header__button { /* Project */
  @layer project {
    /* コンテナクエリを使用したレスポンシブ対応 */
    container-type: inline-size;
  }
}

.u-mb10 { /* Utility */
  @layer utility {
    margin-block-end: var(--space-10);
  }
}

FLOCSSの特徴:

  • レイヤー構造による明確な役割分担
  • BEMの命名規則を基本としながら、より柔軟な運用が可能
  • 日本のWeb開発現場に適した設計思想
  • カスケード層との相性が良く、詳細度の管理が容易

レイヤー構成

Foundation

ブラウザのデフォルトスタイルのリセットや、プロジェクト全体のベーススタイルを定義。

CSS
@layer foundation {
  :root {
    --color-primary: #0077cc;
    --space-unit: 0.5rem;
  }

  body {
    font-family: system-ui;
    line-height: 1.5;
  }
}

Layout

ヘッダーやメインコンテンツなど、サイトの骨格となるレイアウトを定義。

CSS
@layer layout {
  .l-header {
    container: header / inline-size;
    padding-block: var(--space-unit);
  }

  .l-main {
    container: content / inline-size;
    margin-inline: auto;
    max-width: 1200px;
  }
}

Object

  • Component:再利用可能な最小単位のモジュール
  • Project:特定のプロジェクトで使用する固有のパターン
  • Utility:margin、paddingなどの調整用クラス
CSS
/* Component */
@layer component {
  .c-button {
    background: var(--color-primary);
    border-radius: 4px;
    color: white;
  }
}

/* Project */
@layer project {
  .p-articleCard {
    display: grid;
    gap: calc(var(--space-unit) * 2);
  }
}

/* Utility */
@layer utility {
  .u-mt-2 {
    margin-block-start: calc(var(--space-unit) * 2);
  }
}

命名規則

CSS
@layer foundation {
  /* f- プレフィックスは不要 */
  :root {
    --color-primary: #0077cc;
  }
}

@layer layout {
  /* レイアウト接頭辞 */
  .l-container {
    max-width: 1200px;
  }
  .l-grid {
    display: grid;
  }
}

@layer component {
  /* 汎用コンポーネント */
  .c-button {
    /* ブロック */
  }
  .c-button__icon {
    /* エレメント */
  }
  .c-button--large {
    /* モディファイア */
  }
}

@layer project {
  /* プロジェクト固有 */
  .p-articleList {
    /* ブロック */
  }
  .p-articleList__item {
    /* エレメント */
  }
  .p-articleList--featured {
    /* モディファイア */
  }
}

@layer utility {
  /* ユーティリティ */
  .u-mt-4 {
    margin-block-start: 1rem;
  }
}

ディレクトリ構成

ディレクトリ構成
styles/
├── foundation/
│   ├── variables.css    /* カスタムプロパティ */
│   ├── reset.css        /* リセットCSS */
│   └── base.css         /* ベーススタイル */
├── layout/
│   ├── header.css       /* ヘッダー */
│   ├── footer.css       /* フッター */
│   └── grid.css         /* グリッドシステム */
├── object/
│   ├── component/
│   │   ├── button.css   /* 汎用ボタン */
│   │   └── card.css     /* 汎用カード */
│   ├── project/
│   │   ├── header-nav.css  /* ヘッダーナビ */
│   │   └── news-card.css   /* ニュースカード */
│   └── utility/
│       ├── margin.css   /* マージン調整 */
│       └── text.css     /* テキスト調整 */
└── index.css            /* メインのCSS */
CSS
/* index.css */
@layer foundation {
  @import url("foundation/variables.css");
  @import url("foundation/reset.css");
  @import url("foundation/base.css");
}

@layer layout {
  @import url("layout/header.css");
  @import url("layout/footer.css");
  @import url("layout/grid.css");
}

@layer component {
  @import url("object/component/button.css");
  @import url("object/component/card.css");
}

@layer project {
  @import url("object/project/header-nav.css");
  @import url("object/project/news-card.css");
}

@layer utility {
  @import url("object/utility/margin.css");
  @import url("object/utility/text.css");
}

実装例

CSS
/* 基本的なカードコンポーネント */
@layer component {
  .c-card {
    border-radius: 8px;
    padding: var(--space-4);
  }
}

/* プロジェクト固有のニュースカード */
@layer project {
  .p-newsCard {
    container-type: inline-size;
    display: grid;
    gap: var(--space-4);
  }

  .p-newsCard__title {
    font-size: var(--font-size-lg);
    font-weight: bold;
  }

  .p-newsCard__content {
    @container (min-width: 640px) {
      display: grid;
      grid-template-columns: 2fr 1fr;
    }
  }
}

/* レイアウトでの配置 */
@layer layout {
  .l-newsSection {
    display: grid;
    gap: var(--space-8);
    margin-block: var(--space-8);
  }
}

/* ユーティリティでの調整 */
@layer utility {
  .u-shadow {
    box-shadow: var(--shadow-md);
  }
}

このように、各レイヤーの役割を意識しながら、モダンなCSS機能を活用したコンポーネント設計が可能です。

プロジェクトへの導入

段階的な導入手順

CSS
/* 1. カスケード層の定義 */
@layer foundation, layout, component, project, utility;

/* 2. 既存のスタイルを整理 */
@layer foundation {
  /* グローバルなリセットとベーススタイル */
}

/* 3. 新規コンポーネントをFLOCSS化 */
@layer component {
  .c-newFeature {
    /* 新機能から段階的に適用 */
  }
}

チーム開発でのガイドライン

CSS
/* コメントで目的を明確に */
@layer project {
  /* 商品一覧の表示用コンポーネント */
  .p-productList {
    container-type: inline-size;
  }
}

/* コンポーネントの依存関係を明示 */
@layer component {
  /* @require ./button.css */
  .c-buttonGroup {
    display: flex;
    gap: var(--space-2);
  }
}

レビューチェックポイント

  • 適切なレイヤーに配置されているか
  • 命名規則は守られているか
  • 不要な詳細度の上昇がないか
  • カスケード層の使用は適切か

よくある課題と解決策

レイヤー判断の迷い

CSS
/* 迷いやすいケース */
@layer component {
  /* 汎用的なカード */
  .c-card { }
}

@layer project {
  /* 特定のページでのみ使用するカード */
  .p-newsCard { }
}

コンポーネントの粒度

CSS
/* 良い例:単一責任の原則 */
@layer component {
  .c-button {
    /* ボタンの基本スタイルのみ */
  }
}

/* 避けるべき例:責任が多すぎる */
@layer component {
  .c-buttonWithIconAndDropdown {
    /* 複数の機能を1つのコンポーネントに詰め込みすぎ */
  }
}

破綻防止のルール

CSS
@layer project {
  .p-feature {
    /* containerクエリで独立性を保つ */
    container-type: inline-size;
  }

  /* カスタムプロパティで変更に強い設計 */
  .p-feature__heading {
    color: var(--feature-heading-color, var(--color-primary));
  }
}

まとめ – FLOCSSによる持続可能なCSS設計

レイヤーによる明確な責任分離

CSS
@layer foundation { /* ベース設定 */ }
@layer layout { /* 骨格部分 */ }
@layer component { /* 再利用可能なパーツ */ }
@layer project { /* プロジェクト固有の実装 */ }
@layer utility { /* 調整用クラス */ }

設計のポイント

CSS
/* 1. コンポーネントの独立性を保つ */
@layer component {
  .c-button {
    --button-color: var(--color-primary);
  }
}

/* 2. インターフェースを明確に */
@layer project {
  .p-header {
    container-type: inline-size;
  }
}

/* 3. 拡張性を確保 */
@layer utility {
  .u-hidden {
    display: none;
  }
}

FLOCSSは単なるCSS設計手法ではなく、チーム開発を円滑にし、プロジェクトの持続的な成長を支える重要な基盤となります。モダンなCSS機能と組み合わせることで、より強力な設計パターンを実現できます。