メインコンテンツへスキップ
Code & Craft
Web制作 約6分で読めます

CSS Cascade Layers (@layer) 完全ガイド|詳細度戦争を終わらせる新常識

CSS Cascade Layers (@layer)の使い方を実例付きで解説。詳細度の問題を解消し、ライブラリCSSとカスタムCSSを美しく共存させる設計パターンを紹介。

CSS を書いていて最も頭を悩ませるのが 詳細度(Specificity)の問題です。!important を連発したり、意味のないセレクタを長くしたり … そんな時代は終わりました。CSS Cascade Layers(@layer が、カスケードの優先順位を明示的に制御する仕組みを提供します。

Cascade Layers とは

@layer は、CSS のルールを レイヤーにグループ化し、レイヤー間の優先順位を定義できる機能です。これにより、詳細度に関係なくスタイルの上書き順序をコントロールできます。

@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; }
}

@layer base {
  body { font-family: sans-serif; }
}

@layer components {
  .button { padding: 0.5rem 1rem; background: blue; }
}

@layer utilities {
  .text-red { color: red; }
}

後に宣言されたレイヤー(utilities)の方が優先されます。!important を使わずに、レイヤー順だけで上書き順序が決まります。

ブラウザ対応(2026年4月)

ブラウザサポート開始
Chrome 992022年3月
Firefox 972022年2月
Safari 15.42022年3月
Edge 992022年3月

全主要ブラウザで 4 年以上前からサポートされており、実務投入に十分な成熟度です。

従来の詳細度問題

/* ライブラリの CSS */
.btn.btn-primary { background: blue; }
/* 詳細度: 0,2,0 */

/* 上書きしたい */
.btn-primary { background: red; }
/* 詳細度: 0,1,0 → 負ける */

/* やむなく詳細度を上げる */
.page .btn.btn-primary { background: red; }
/* 詳細度: 0,3,0 */

/* もっと上書きしたい時は... */
.btn.btn-primary { background: red !important; }

このような「詳細度戦争」は、メンテナンス性を著しく低下させます。

Cascade Layers での解決

@layer library, overrides;

@layer library {
  .btn.btn-primary { background: blue; }
  /* 詳細度: 0,2,0 */
}

@layer overrides {
  .btn-primary { background: red; }
  /* 詳細度: 0,1,0 だが、レイヤー順で勝つ */
}

overrides レイヤーが後に宣言されているため、詳細度が低くても library レイヤーより優先されます。

レイヤーの優先順位ルール

  1. レイヤー外のスタイル > レイヤー内のスタイル
  2. 複数レイヤー間: 後に宣言されたレイヤー > 先に宣言されたレイヤー
  3. 同じレイヤー内: 通常の詳細度ルールが適用
  4. !important は順序が逆転: 最初に宣言されたレイヤーの !important が勝つ

レイヤー外

@layer base {
  .btn { background: blue; }
}

/* レイヤー外 - どんな詳細度でも勝つ */
.btn { background: red; }

順序の宣言

レイヤーは最初に空で宣言してから順序を定義するのがベストプラクティスです。

/* 順序を定義 */
@layer reset, base, layout, components, utilities;

/* 後から任意の順序で内容を追加 */
@layer components {
  .button { ... }
}

@layer reset {
  * { ... }
}

実践パターン1: デザインシステムの構築

/* すべてのレイヤーを最初に宣言 */
@layer reset, base, layout, components, patterns, utilities, overrides;

/* 1. Reset */
@layer reset {
  *, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }
}

/* 2. Base */
@layer base {
  :root {
    --color-primary: #0284c7;
    --color-text: #1e293b;
  }
  body {
    font-family: system-ui;
    color: var(--color-text);
  }
}

/* 3. Layout */
@layer layout {
  .container { max-width: 1200px; margin: 0 auto; }
  .grid { display: grid; gap: 1rem; }
}

/* 4. Components */
@layer components {
  .button {
    padding: 0.5rem 1rem;
    border-radius: 0.25rem;
    background: var(--color-primary);
    color: white;
  }
}

/* 5. Patterns */
@layer patterns {
  .card {
    border: 1px solid #e2e8f0;
    padding: 1rem;
    border-radius: 0.5rem;
  }
}

/* 6. Utilities */
@layer utilities {
  .text-center { text-align: center; }
  .mt-4 { margin-top: 1rem; }
}

/* 7. Overrides(必要時のみ) */
@layer overrides {
  /* 特殊なケースの上書き */
}

実践パターン2: 外部ライブラリとの共存

外部ライブラリ(例: Bootstrap)をレイヤーでインポートすると、カスタムスタイルで簡単に上書きできます。

/* ライブラリを library レイヤーに */
@import url('bootstrap.css') layer(library);

/* カスタムスタイルは library より後のレイヤーに */
@layer custom {
  .btn-primary {
    background: var(--brand-color);
    /* 詳細度を上げる必要なし */
  }
}

Bootstrap の .btn.btn-primary (詳細度 0,2,0) をカスタムの .btn-primary (詳細度 0,1,0) で上書きできます。

ネストされたレイヤー

レイヤーは階層化も可能です。

@layer framework {
  @layer base, components;

  @layer base {
    body { font-family: sans-serif; }
  }

  @layer components {
    .button { padding: 0.5rem; }
  }
}

/* framework.base 内のルール */
@layer framework.base {
  h1 { font-size: 2rem; }
}

親レイヤーの優先順位が適用されたうえで、子レイヤー内の順序も守られます。

無名レイヤー

名前なしでレイヤーを宣言することもできます。

@layer {
  .card { padding: 1rem; }
}

ただし、後から追加できないため、基本的には名前付きレイヤーを推奨します。

@import との併用

/* 順序を事前に宣言 */
@layer reset, base, components;

/* @import でレイヤーに入れる */
@import url('reset.css') layer(reset);
@import url('tailwind.css') layer(base);
@import url('custom-components.css') layer(components);

これにより、外部 CSS ファイルもレイヤーで管理できます。

ITCSS との相性

ITCSS(Inverted Triangle CSS)という詳細度ベースの設計手法があり、Cascade Layers と非常に相性が良いです。

1. Settings   → @layer settings
2. Tools      → @layer tools
3. Generic    → @layer generic
4. Elements   → @layer elements
5. Objects    → @layer objects
6. Components → @layer components
7. Utilities  → @layer utilities
@layer settings, tools, generic, elements, objects, components, utilities;

Tailwind CSS v4 での活用

Tailwind CSS v4 では Cascade Layers を前提とした設計になっています。

@layer theme, base, components, utilities;

@layer theme {
  :root {
    --color-blue-500: #0ea5e9;
  }
}

/* Tailwind が自動的に layers に振り分け */

注意点

1. !important の挙動が逆転

通常の CSS では !important最後に書かれたものが勝つですが、Cascade Layers では 最初のレイヤーに書かれた !important が勝ちます。

@layer first, second;

@layer first {
  .btn { background: blue !important; }
}

@layer second {
  .btn { background: red !important; }
}

/* 結果: blue(first レイヤーの !important が勝つ) */

2. 既存プロジェクトへの導入

既存プロジェクトに導入する場合、段階的に行うのがおすすめです。

/* 既存CSSはレイヤー外に残す */
.existing-styles { ... }

/* 新規CSSだけレイヤー化 */
@layer new-styles {
  .new-component { ... }
}

レイヤー外のスタイルは、どのレイヤーよりも優先されるため、既存のスタイルを壊しません。

まとめ

CSS Cascade Layers の導入により、以下が実現できます。

  • 詳細度戦争の終結: !important を使わない
  • ライブラリとの共存: 外部 CSS を簡単に上書き
  • 設計の明確化: スタイルの役割と順序を宣言的に表現
  • 保守性の向上: スタイルの優先順位が予測可能

まずは小規模なプロジェクトで試してみて、@layer reset, base, components, utilities; の 4 層構成から始めるのがおすすめです。

参考リンク

#CSS #カスケード #設計 #フロントエンド
シェア: