この記事の目次
外部の部品用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
記事の内容を、課題で確かめる
記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。