RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

【CSS実装予定】カスケードレイヤー「@layer」について

f:id:tech-rakus:20211210142026p:plain

注意

カスケードレイヤーは正式実装の機能ではないため、これから仕様変更の可能性があります。

目次

はじめに

こんにちは、フロントエンドチームのta_kameです。
今回は、今後実装されるかもしれないCSSの新機能カスケードレイヤー(Cascade Layers)について紹介します。

CSS設計では詳細度をなるべく均一に保つよう行いたいですが、 レガシー案件であったり、サードパーティーCSSが導入されている案件だと、 なかなか管理が大変です。

そこで紹介したいのがカスケードレイヤーです。

カスケードについて

そもそもカスケードとは何か、ということになりますが、簡単に言うと、スタイルを適用するための優先順位のルールをまとめたものになります。CSSファイルを複数読み込んだり、同CSSファイル内でも複数箇所で書かれていたり、そういった場合どのスタイルが適用されるのか…ということです。一番よく気にする機会は詳細度かもしれません。

詳細度以外ではとくに意識することは少ないかもしれませんが、カスケードレイヤーについて紹介する前にまずは現在の仕様について確認してみます。

現在のCSSが適用される優先順位を決めるためのカスケードのルールはこちらです。

  1. Origin and Importance
  2. Context
  3. Specificity
  4. Order of Appearance

英語の記述をそのまま引用してきたために、このままではわかりづらいので、1つずつ説明します。

Origin and Importance

Originとはユーザーエージェントスタイルシート、ページ作成者スタイルシート、ユーザースタイルシートなど、スタイルがどこで宣言されているかを示しています。
そしてImportanceとはCSSに記述する!importantのことです。
Origin and Importanceとはそれらの組み合わせの優先順位によるもので、下記の優先順位で適用されます。

  1. トランジション
  2. ユーザーエージェント (!important)
  3. ユーザー (!important)
  4. 作成者 (!important)
  5. アニメーション
  6. 作成者 (通常)
  7. ユーザー (通常)
  8. ユーザーエージェント (通常)

Context

ContextとはShadow DOMなどのネストされたコンテキストの優先順位です。
異なるカプセル化されたコンテキストからの宣言では、下記のルールで優先されます。

  1. 通常:外部コンテキストからの宣言が優先
  2. important:内部コンテキストからの宣言が優先

言い換えると通常の宣言同士であれば外側から容易に書き換えることができるが、内側のimportantは外側からは書き換えられないということになります。

Specificity

詳細度による優先順位です。
IDセレクターや要素セレクターなどの種類や数によって、一番詳細度の高い宣言が優先されます。

Order of Appearance

宣言が登場する順番による優先順位です。
ドキュメントの後ろの方で登場した宣言が優先されます。

カスケードレイヤーについて

カスケードレイヤーが実装された場合のカスケードのルールは下記の通りになります。

  1. Origin and Importance
  2. Context
  3. The Style Attribute
  4. Layers
  5. Specificity
  6. Order of Appearance

The Style Attribute

style属性の優先順位です。
現在style属性はOrder of Appearance内で定義されており、すべてのスタイルシートのあとに宣言されるとされています。
カスケードレイヤー実装のタイミングではわかりやすく、独立となるようです。

Layers

カスケードレイヤーは新設で配置されます。
カスケードレイヤーにより詳細度や登場順の影響を受けることなく、制御ができることになります。

従来のCSS

従来のカスケードのルールとカスケードレイヤーが実装された場合の違いを確認したところで、まずは従来のCSSのサンプルコードを紹介します。

<main id="container">
  <div class="block">
    <p class="text">カスケードレイヤー</p>
  </div>
</main>
#container .block .text {
  color:blue;
}
p {
  color:red;
}

f:id:ta_kame:20211202174525p:plain
大げさに詳細度を高めていますが、こちらは当然テキストのスタイルはです。

カスケードレイヤーの記述方法について

それではカスケードレイヤーを使用してみましょう。
具体的な記述方法ですが、@layerのあとに好きなレイヤー名をつけて、その中にスタイルを書いていくだけです。

@layer main{
  #container .block .text {
    color:blue;
  }
}

p {
  color:red;
}

f:id:ta_kame:20211202174627p:plain
color:blueの方が詳細度は明らかに高くみえますが、テキストはです。

つまりレイヤー化されていないスタイルが一番強くなります
詳細度がいくら高くても関係なく、レイヤー順の方が優先されます。

複数レイヤー

レイヤーは複数記述することも可能です。
先にレイヤー名を宣言しておくと、順番を並び替えるだけでスタイルが適用されるので、より管理が楽になります。

@layer main;
@layer second;

@layer main {
  #container .block .text {
    color: blue;
  }
}

@layer second {
  #container .block .text {
    color: green;
  }
}

f:id:ta_kame:20211202174719p:plain
最初の宣言で@layer secondが後に宣言されているので テキストはです。

ここでmainレイヤーとsecondレイヤーの宣言を逆にしてみます。

@layer second;
@layer main;

@layer main {
  #container .block .text {
    color: blue;
  }
}

@layer second {
  #container .block .text {
    color: green;
  }
}

f:id:ta_kame:20211202174525p:plain
すると、この場合のテキストはになります。

現在mainレイヤーがあとに宣言されているのでmainレイヤーのスタイルがあたっています。

もしmainとsecondの別々のレイヤーで詳細度がそれぞれ異なる場合はどうなるでしょうか。
ためしにmainレイヤーの詳細度を下げてみます。

@layer second;
@layer main;

@layer main {
 p {
    color: blue;
  }
}

@layer second {
  #container .block .text {
    color: green;
  }
}

f:id:ta_kame:20211202174525p:plain
少し違和感があるかもしれませんが、 この場合でもテキストはになります。

詳細度よりとにかくレイヤー順の方が優先されます。

使用例(リファクタリング

リファクタリング後のCSSは後述する起動オプション付きでブラウザを実行しないとスタイルが適用されませんのでご注意ください。

それではカスケードレイヤーはどのような場面で活躍するか…今回はカスケードレイヤー設計の観点で考えてみます。

たとえば、既存プロジェクトで大きなCSSファイルがあるとします。
ファイルを分割したいと思うのですが、まずは1ファイル内で安全に行うべく、カスケードレイヤーを使用してリファクタリングを試みます。

そこで多少ひどいCSSをここに用意しました。

修正前のコード

こちらのHTMLとCSSを使って、CSSリファクタリングを行っていきます。

リファクタリングの準備

まず、今回機能として紹介していませんが@importでCSS内に別のCSSを読み込むことができます。
@importはすでに実装済みの機能ですが、カスケードレイヤーと組み合わせると名前付きでimportが可能となります。せっかくなのでHTMLでは1つのCSSを読み込むようにして、名前付きimportしてみます。
そして、いったんリファクタリング用のレイヤーに既存のCSSをすべて入れます。

余談ですが、CSSの@importはパラレルロードではないため、CSS設計を考える段階でSassの導入を検討してみてもよいかもしれません。今回はあくまでPureCSSということを前提としています。

@import url(https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css)
layer(normalize);

@layer refactoring {
  body {
    font-size: 16px;
  }

  #header {
    padding: 20px;
  }

  #header .logo {
    height: 50px;
    width: 200px;
    background-color: blue;
    color: #fff;
    display: table;
  }

  #header .logo span {
    vertical-align: middle;
    display: table-cell;
    text-align: center;
  }

  .headline1,
  .headline2,
  .headline3,
  .title {
    font-weight: bold;
  }

  h4.title {
    font-weight: 500;
  }

  .container {
    padding: 16px;
  }
  .container .list {
    list-style: circle;
  }
  .container .list .item {
    letter-spacing: 1px;
  }
  .container .list .item:nth-child(2) {
    color: red;
  }

  .container .box {
    display: flex;
    flex-wrap: wrap;
  }
  .container .box .media {
    padding: 8px;
    margin: 4px;
    width: calc(50% - 8px) !important;
    box-sizing: border-box;
    background-color: yellow;
  }
  .container .box .media .img {
    width: 100%;
    height: 100px;
    background-color: green;
  }
}

FLOCSS化

ここからFLOCSS化します。

まずはHTMLにクラスを付与するのですが、ためしにlist部分へ手を入れます。

      <h2 class="headline1 c-headline1">LIST</h2>
      <ul class="list c-list">
        <li class="item c-list__item">HTML</li>
        <li class="item c-list__item c-list__item--em">CSS</li>
        <li class="item c-list__item">JavaScript</li>
      </ul>

クラスを足しただけなので、何も変わりません。 そこにカスケードレイヤーを足します。

@layer c-list; /* ① */
@layer refactoring; /* ② */

@layer refactoring {
...
}
@layer c-list {
  .c-list {
    list-style: circle;
  }
  .c-list__item {
    letter-spacing: 1px;
  }
  .c-list__item--em {
    color: blue;
  }
}

f:id:ta_kame:20211129164953p:plain
試しにc-list__item--emへcolor:blueのスタイルを適用させようとしていますが、 現在の状態はrefactoringレイヤーの方があとに宣言されているので結局何も変わりません。

何も変わっていないことが確認できたので、①と②を入れ替えます。

@layer refactoring; /* ① */
@layer c-list; /* ② */

f:id:ta_kame:20211129165152p:plain
c-listレイヤーのスタイルが適用されました。
うまくいっているので、同様に切り分けながらリファクタリングを進めます。

どこまで分割するかという問題があるかもしれませんが、今回は以下のようなコードになりました。

リファクタリング

※後述の起動オプション付きでブラウザを実行しないとスタイルが適用されないのでご注意ください。

1つのcssファイル内で分割が完了しました。
ここからファイルを分割していき、@importを使用して読み込むようにすれば完成となります。

カスケードレイヤーをブラウザで使う方法

使い方ですが、現在実験的機能のためFirefox NightlyかGoogle Canaryでしか試すことができません。
起動オプションを設定して実行すると使えるようになりますのでご紹介します。

Windows

Windowsはショートカットのプロパティに起動オプションを追加して実行するだけで使えるようになります。

"C:\Users\username\AppData\Local\Google\Chrome SxS\Application\chrome.exe" --enable-blink-features=CSSCascadeLayers

f:id:ta_kame:20211119111505p:plain

画像のように「サポートされていないコマンドライン フラグ --enable-blink-features=CSSCascadeLayersを使用しています。
これにより安全性とセキュリティが損なわれます。」と表示されていたらカスケードレイヤーが使えるようになっています。

f:id:ta_kame:20211105164637p:plain

Mac

Macの場合はターミナルから起動します。通常起動は下記コマンドで実行できます。

open -a /Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary

こちらに起動オプションを追加して実行します。

open -a /Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --args --enable-blink-features=CSSCascadeLayers

Windowsと同様にメッセージが表示されていればカスケードレイヤーが使用できるようになっています。 f:id:ta_kame:20211119113948p:plain

また、毎回コマンド入力するのは手間なので、よく使う場合はAutomatorの設定を行います。AutomatorはLaunchpadから起動できます。
f:id:ta_kame:20211119112155p:plain

シェルスクリプトを実行」から、起動オプション付きのコードを貼り付けます。
f:id:ta_kame:20211119114354p:plain

完了しましたら、メニューバーより「ファイル」→「保存」を選択して保存します。
この時フォーマットは「アプリケーション」としておきます。
f:id:ta_kame:20211119114736p:plain

これで次回以降はアイコンをクリックするだけで起動オプション付きのChrome Canaryが実行できます。
f:id:ta_kame:20211119115136p:plain

注意

開発者向けの機能のため、ブラウザが意図しない挙動をするかもしれないので、使用についてはあくまで機能の確認程度に留めていた方がいいかもしれません。

最後に

今回はカスケードレイヤー(@layer)について紹介しました。
まだ実験的機能としてですが、カスケードレイヤーがCSS設計やリファクタリングで活躍する日がくるかもしれません。

Sassのような記述ができるCSSネスティングや、条件分岐ができるwhenなど、CSSには他にも実装が期待されている機能はたくさんあります。
興味のある方はぜひ調べてみてくださいね。

参考

Cascade Layers? - CSS-Tricks

The Future of CSS: Cascade Layers (CSS @layer) – Bram.us

CSSのCascadingに追加されようとしているLayerという概念

CSS Cascading and Inheritance Level 4

CSS カスケード入門 - CSS: カスケーディングスタイルシート | MDN

id:ta_kame Takao Kamenoue


  • エンジニア中途採用サイト
    ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
    ご興味ありましたら是非ご確認をお願いします。
    20210916153018
    https://career-recruit.rakus.co.jp/career_engineer/

  • カジュアル面談お申込みフォーム
    どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
    以下フォームよりお申込みください。
    rakus.hubspotpagebuilder.com

  • イベント情報
    会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください!
    rakus.connpass.com

Copyright © RAKUS Co., Ltd. All rights reserved.