[CSS] カスケードレイヤー(@layer)とITCSSの概念を組み合わせた設計を考える

4 min read

カスケードレイヤーとは

CSS の Cascading に Layers という概念が追加される。

これまでのカスケードのソート順序は以下の判定基準に基づいてソートされる(後述の方が優先される)。

  1. 出自と重要度(Origin and Importance)
  2. 文脈(Context)
  3. 要素に付されたスタイル(Element-Attached Styles)
  4. 詳細度(Specificity)
  5. 出現順序(Order of appearance)

Layers が追加されることで以下のような判定基準に基づく。

  1. 出自と重要度(Origin and Importance)
  2. 文脈(Context)
  3. 要素に付されたスタイル(Element-Attached Styles)
  4. 層(Layers)
  5. 詳細度(Specificity)
  6. 出現順序(Order of appearance)

サンプルコード

カスケードレイヤーに委ねるだけで詳細度や記述順などを気にせず書くことができる。

/* layerの優先度順を定義する */
@layer first, second;

/* 
  secondのあとにfirstが書かれてあるが、冒頭のlayerの優先度の定義により
  .test は `display: block` が適用される
*/
@layer second {
  .test {
    display: block;
  }
}

@layer first {
  .test {
    display: none;
  }
}

カスケードレイヤーの細かい仕様については割愛。

対応状況

2022 年 1 月現在、下記のブラウザのバージョンにおいてサポートされている。なお、それより古いバージョンでも設定によって有効にできるものもある。ただし、現状はモバイル端末のブラウザで利用できるものはないようだ。

  • Firefox: 97-
  • Chrome: 99-
  • Edge: 99-
  • Safari: 15.4-

参照: https://caniuse.com/css-cascade-layers

ITCSS のレイヤー

ITCSS で提唱されているレイヤーは以下の通り。

  1. Settings
  2. Tools
  3. Generic
  4. Base
  5. Objects
  6. Components
  7. Utilities

ITCSS のレイヤーをカスケードレイヤーに落とし込む

ITCSS のSettingsToolsに関しては、プリプロセッサ上で利用する変数の定義、mixin、CSS Custom Properties などを利用したものが主になる。そのため、それらのレイヤーについては、カスケードレイヤー上での定義は割愛する。

ITCSS のレイヤーをカスケードレイヤーで表現すると以下のようになる。

@layer Generic, Base, Objects, Components, Utilities;

@layer Generic {
  * {
    box-sizing: border-box;
  }
}

@layer Base {
  ul {
    list-style: square outside;
  }
}

@layer Objects {
  .ui-list {
    margin: 0;
    padding: 0;
    list-style: none;
  }
}

@layer Components {
  .products-list {
    border-top: 1px solid #999;
  }
}

@layer Utilities {
  .one-half {
    width: 50%;
  }
}

読み込み順の定義

@layer Generic, Base, Objects, Components, Utilities;

Generic の詳細度が最も低く、Utilities の詳細度が最も高くなる。

下記のように@layerの定義の順番が一致しなくても、上記の定義順の詳細度になる。

/**
 * @layer Generic, Base, Objects, Components, Utilities;
 * となっているので、Utilitiesが先に書かれてあっても、Baseの方が詳細度が低い扱いになる
 */
@layer Utilities {
  .test {
    display: none;
  }
}

@layer Generic {
  .test {
    display: block;
  }
}

参考