HTML / CSS公開 約9分

CSS cascade layersで優先順を決める:外部CSSとサイトの指定を分ける

外部CSSを上書きするために、IDやクラスを増やし続けていませんか。外部スタイルをレイヤーへ取り込む小さな見本で、宣言順と詳細度の関係を比較します。レイヤー外に残った指定とimportantの境界も確認します。

この記事の目次
  1. セレクターを比べる前に、所属レイヤーを比べる
  2. 外部CSSをvendorへ取り込む三つのファイル
  3. レイヤー外に残った一行が、優先順を飛び越える
  4. 順序を直す場所は、後のブロックではなく最初の宣言
  5. importantや継承まで、同じ順位表へ押し込まない
  6. 色と、残った枠を組にして確認する

外部の部品用CSSにID付きのセレクターがあり、サイト側でクラスを増やさないと色を変えられない。追加した規則を別ページでさらに上書きするうち、どの指定を直すべきか追いにくくなることがあります。外部部品とサイトの指定を、レイヤーというまとまりへ分けて優先順を決めます。

HTMLと外部CSSの読込みが分かり、CSSの適用元を調べる記事の詳細度を確認した人向けです。架空の講座案内で、外部CSSの代わりとなる短いファイルを自作します。ライブラリは導入せず、三つの練習ファイルで読込みと適用の関係を確かめます。

セレクターを比べる前に、所属レイヤーを比べる

カスケードは、同じ要素の同じプロパティへ複数の宣言が当たったとき、使う値を決める仕組みです。cascade layersは、スタイルを名前付きのまとまりへ分け、そのまとまり同士の優先順を指定します。

今回の比較は、作者が書く通常の宣言だけです。important、インライン指定、アニメーション、トランジションは使いません。この条件では、後に定義したレイヤーの宣言が前のレイヤーより優先されます。別レイヤー間では、セレクターの詳細度を先に競わせません。

たとえば@layer base, vendor, site;と最初に書けば、通常宣言はsite、vendor、baseの順に優先されます。siteのクラス一つでも、vendorのID付きの規則より優先できます。同じレイヤーの中では詳細度などの比較が残ります。詳細度の説明を、比較する段階ごとに読むのがポイントです。

比較する二つの通常宣言 この教材で先に見るもの
vendorとsite 最初に定義したレイヤーの順序
site内の二つの規則 詳細度。同じなら記述順など
レイヤー内とレイヤー外 レイヤー外が優先される

レイヤー名には決まった強さがありません。siteという名前だから強いのではなく、最初の順序宣言で後ろへ置いたためです。z-indexのように箱を手前へ重ねる指定とも異なります。

外部CSSをvendorへ取り込む三つのファイル

新しい練習フォルダに、次の三ファイルを同じ階層で保存します。まずvendor.cssです。外部部品に強いセレクターがある状況を再現します。

#lesson .note {
  color: #6b3fa0;
  border: 3px solid currentColor;
  padding: 16px;
}

次がsite.cssです。順序を宣言した後、importでvendor.cssをvendorレイヤーへ取り込みます。importは通常のスタイル規則より前へ置きます。レイヤー名だけを宣言する文は、その前へ置けます。importの公式リファレンスでこの構文を確認できます。

@layer base, vendor, site;
@import url('./vendor.css') layer(vendor);

@layer base {
  * { box-sizing: border-box; }
  body { margin: 16px; font-family: sans-serif; line-height: 1.8; color: #222; }
  main { max-width: 560px; margin: auto; }
  a:focus-visible { outline: 3px solid #174ea6; outline-offset: 3px; }
}
@layer site {
  .note { color: #943c20; }
}

最後にlayer.htmlです。vendor.cssを別のlinkでも読まないようにします。site.cssのimportが読込みを担当します。

<!doctype html>
<html lang="ja"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>講座案内のスタイル順</title>
<link rel="stylesheet" href="./site.css">
</head><body><main id="lesson">
<h1>講座案内(架空の練習)</h1>
<p class="note">開始前に、用意する道具を確認してください。</p>
<p><a href="#tools">道具の一覧へ</a></p>
<section id="tools"><h2>道具</h2><p>紙、鉛筆、定規を用意します。</p></section>
</main></body></html>

同じフォルダでpython3 -m http.server 8767 --bind 127.0.0.1を実行し、http://127.0.0.1:8767/layer.htmlを開きます。終了はCtrl+Cです。既にポートが使われている場合は、空いている番号へ変えてください。

期待する文字色はsiteの茶色#943c20です。枠と内側余白はvendorの指定が残ります。レイヤーの優先はファイル全体を採用・不採用にする仕組みではなく、競合するプロパティごとに働くためです。枠のcurrentColorはその要素のcolorを使うので、枠も茶色になります。

レイヤー外に残った一行が、優先順を飛び越える

第一の失敗を再現するには、site.cssの末尾へ次を追加します。どのレイヤーブロックにも入れないでください。

.note { color: #176044; }

色は緑へ変わります。siteが最後のレイヤーでも、同じ作者の通常宣言ではレイヤー外の宣言が優先されます。layerのリファレンスが説明する関係です。site側へIDを追加しても、この比較段階は変わりません。

緑が古い仮指定なら削除します。残す規則なら、役割に合うレイヤーへ移し、その中でどちらの値を採るか決めます。今回の修正は追加した一行を削除し、文字と枠が茶色へ戻ることを確かめる方法です。

vendor.cssを通常のlinkでも読み込むと、外部の指定をレイヤー外へ二重に導入してしまいます。移行時には、包んだ新しい経路と古い読込みを同時に残さないよう確認します。ファイルが届いていない疑いはCSSの配信内容を確認する記事で扱い、優先順の問題と切り分けます。

順序を直す場所は、後のブロックではなく最初の宣言

第二の失敗は、最初の行が@layer base, site, vendor;なのに、ファイル末尾へ@layer site { ... }を書けばsiteが強くなると考えることです。既にある名前のレイヤーを開き直しても、その順序は後ろへ移りません。vendorが後なら、例の色は紫になります。

修正は最初の行を@layer base, vendor, site;へ戻すことです。後から別順の一覧を足して並べ替えようとしません。実ページでは別ファイルが先に名前を定義している可能性もあるため、読込み全体で最初の宣言を探します。

再確認では、完成例の末尾へ@layer vendor { #lesson .note { color: #6b3fa0; } }を足します。vendorへ規則を追加しても、最初の順序が同じなら茶色のままです。最初の宣言が「並びを決める場所」、後のブロックが「その所属へ規則を足す場所」だと区別できます。確認後は追加したブロックを外します。

importantや継承まで、同じ順位表へ押し込まない

important付きの宣言ではレイヤー順が逆になり、レイヤー内のimportantはレイヤー外のimportantより優先されます。通常宣言を整理した今回の表へ、そのまま混ぜてはいけません。vendor側のcolorだけにimportantを足せば、siteの通常宣言より優先されることも確認できます。

また、bodyのcolorと子の.noteのcolorは、同じ要素に当たる二つの宣言ではありません。親から継承できる値より、子自身へ指定された値が使われる場面を「レイヤー順が逆転した」と判断しないようにします。

小さなページで一つの不要な規則を消せば済むなら、レイヤー構成を増やす必要はありません。外部CSS、基本スタイル、部品、用途別の調整を継続して組み合わせる場合に、順序を明示する価値があります。レイヤー自体はセレクターの適用範囲をDOMの一部へ限定する機能でもありません。

色と、残った枠を組にして確認する

15分程度で、下の条件を一つずつ試し、毎回完成例へ戻します。色は開発者ツールの計算済みcolorでも照合してください。

変更 期待するcolor
完成例 茶色 #943c20
レイヤー外へ緑の一行を追加 緑 #176044
その一行を削除 茶色 #943c20
最初の順序だけbase, site, vendorへ変更 紫 #6b3fa0
順序を戻し、vendorのcolorだけimportantへ変更 紫 #6b3fa0

追加課題ではsite側にpadding: 24pxを加えます。期待する結果は茶色の文字、3pxの枠、24pxの内側余白です。枠の太さまで消えないことから、プロパティごとの競合を確認できます。レスポンシブCSSの無料レッスンで規則を直す際も、適用される値と、その規則が属する場所を一組でたどれます。

TRY A LESSON

記事の内容を、課題で確かめる

意味のあるHTMLを書く練習 →

HTMLの学習内容 →

記事についてのお問い合わせ

記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。

← 記事一覧に戻る