層疊層
本課程旨在向您介紹級聯層,這是一種更高階的功能,它建立在 CSS 級聯和 CSS 特異性的基本概念之上。
如果您是 CSS 新手,立即學習本課程可能不那麼相關,而且比課程的其他部分更具學術性。然而,瞭解級聯層的基本知識有助於您在專案中遇到它們。您使用 CSS 的次數越多,瞭解級聯層並知道如何利用其強大功能將為您節省大量管理來自不同方、外掛和開發團隊的 CSS 程式碼庫的痛苦。
當您處理來自多個源的 CSS 時,如果存在相互衝突的 CSS 選擇器和相互競爭的特異性,或者當您考慮使用 !important 時,級聯層最相關。
對於應用於元素的每個 CSS 屬性,只能有一個值。您可以透過在瀏覽器的開發工具中檢查元素來檢視應用於元素的所有屬性值。該工具的“樣式”面板顯示應用於被檢查元素的所有屬性值,以及匹配的選擇器和 CSS 原始檔。來自具有優先順序的源的選擇器將其值應用於匹配的元素。
除了應用的樣式外,“樣式”面板還會顯示劃掉的值,這些值與選定的元素匹配,但由於級聯、特異性或源順序而未應用。劃掉的樣式可能來自具有優先順序的同一源,但特異性較低,或者源和特異性匹配,但它們在程式碼庫中較早出現。對於任何應用的屬性值,可能會有多個來自許多不同源的宣告被劃掉。如果您看到一個劃掉的樣式,其選擇器具有更大的特異性,則表示該值缺少源或重要性。
通常,隨著網站複雜性的增加,樣式表的數量也會增加,這使得樣式表的源順序變得更加重要和複雜。級聯層簡化了在此類程式碼庫中維護樣式表。級聯層是顯式特異性容器,可對最終應用的 CSS 宣告提供更簡單、更強大的控制,使 Web 開發人員能夠優先處理 CSS 的各個部分,而無需與特異性作鬥爭。
要理解級聯層,您必須很好地理解 CSS 級聯。下面的部分簡要回顧了重要的級聯概念。
級聯概念回顧
CSS 中的“C”代表“級聯”。它是樣式級聯在一起的方法。使用者代理會執行幾個明確定義的步驟來確定每個元素的每個屬性的值。我們將在此處簡要列出這些步驟,然後深入探討步驟 4,即級聯層,這正是您來此學習的內容
- 相關性:查詢每個元素的具有選擇器匹配的所有宣告塊。
- 重要性:根據規則是正常還是重要進行排序。重要樣式是那些設定了
!important標誌的樣式。 - 來源:在兩個重要性桶中的每一箇中,按作者、使用者或使用者代理來源對規則進行排序。
- 級聯層:在六個來源重要性桶中的每一箇中,按級聯層進行排序。正常宣告的層順序是從建立的第一個層到最後一個層,然後是未分層的正常樣式。此順序對於重要樣式是反向的,未分層的重要樣式具有最低優先順序。
- 特異性:對於具有優先順序的源層中的競爭樣式,按特異性對宣告進行排序。
- 作用域鄰近度:當具有優先順序的源層中的兩個選擇器具有相同的特異性時,作用域規則中到作用域根的 DOM 層次結構中跳數最少者獲勝。有關更多詳細資訊和示例,請參閱如何解決
@scope衝突。 - 出現順序:當具有優先順序的源層中的兩個選擇器具有相同的特異性和作用域鄰近度時,來自最後一個宣告的具有最高特異性的選擇器的屬性值獲勝。
對於每個步驟,只有“仍在執行”的宣告才會進入下一步“競爭”。如果只有一個宣告在執行,它就“贏了”,後續步驟也就無關緊要了。
來源和級聯
有三種級聯來源型別:使用者代理樣式表、使用者樣式表和作者樣式表。瀏覽器按來源和重要性將每個宣告分為六個來源桶。有八個優先順序級別:六個來源桶、正在過渡的屬性和正在動畫的屬性。優先順序順序從優先順序最低的正常使用者代理樣式,到當前應用的動畫中的樣式,再到重要的使用者代理樣式,然後是正在過渡的樣式,後者具有最高優先順序
- 使用者代理正常樣式
- 使用者正常樣式
- 作者正常樣式
- 正在動畫的樣式
- 作者重要樣式
- 使用者重要樣式
- 使用者代理重要樣式
- 正在過渡的樣式
“使用者代理”是瀏覽器。“使用者”是網站訪問者。“作者”是您,開發人員。直接在元素上使用 <style> 元素宣告的樣式是作者樣式。不包括動畫和過渡樣式,使用者代理正常樣式具有最低優先順序;使用者代理重要樣式具有最高優先順序。
來源和特異性
對於每個屬性,根據權重(正常或重要)具有優先順序的來源中的宣告“獲勝”。暫時忽略層,將應用優先順序最高的來源的值。如果獲勝來源對於一個元素有多個屬性宣告,則比較那些競爭屬性值的選擇器的特異性。不同來源的選擇器之間從不比較特異性。
在下面的示例中,有兩個連結。第一個沒有應用作者樣式,因此只應用使用者代理樣式(以及您的個人使用者樣式,如果有的話)。第二個的 text-decoration 和 color 由作者樣式設定,即使作者樣式表中的選擇器的特異性為 0-0-0。作者樣式“獲勝”的原因是,當來自不同來源的樣式衝突時,將應用來自具有優先順序的來源的規則,而不管沒有優先順序的來源中的特異性如何。
<p><a href="https://example.org">User agent styles</a></p>
<p><a class="author" href="https://example.org">Author styles</a></p>
:where(a.author) {
text-decoration: overline;
color: red;
}
在撰寫本文時,使用者代理樣式表中的“競爭”選擇器是 a:any-link,其特異性權重為 0-1-1。雖然這比作者樣式表中的 0-0-0 選擇器大,但即使您當前的使用者代理中的選擇器不同,也無關緊要:作者和使用者代理來源的特異性權重從不比較。瞭解有關如何計算特異性權重的更多資訊。
來源優先順序總是勝過選擇器特異性。如果一個元素屬性在多個來源中用正常樣式宣告進行樣式化,作者樣式表將始終覆蓋在使用者或使用者代理樣式表中宣告的冗餘正常屬性。如果樣式很重要,使用者代理樣式表將始終勝過作者和使用者樣式。級聯來源優先順序確保來源之間的特異性衝突永遠不會發生。
在繼續之前,最後一點:出現順序只有在優先順序來源中的競爭宣告具有相同的特異性時才變得相關。
級聯層概述
我們現在瞭解了“級聯來源優先順序”,但什麼是“級聯層優先順序”?我們將透過解決級聯層是什麼、它們如何排序以及樣式如何分配給級聯層來回答這個問題。我們將介紹常規層、巢狀層和匿名層。讓我們首先討論級聯層是什麼以及它們解決了哪些問題。
級聯層優先順序順序
與我們根據來源和重要性具有六個優先順序級別類似,級聯層使我們能夠在任何這些來源中建立子來源級別的優先順序。
在六個來源桶中的每一箇中,可以有多個級聯層。層的建立順序非常重要。正是建立順序設定了來源內層之間的優先順序順序。
在正常來源桶中,層按每個層的建立順序排序。優先順序順序是從建立的第一個層到最後一個層,然後是未分層的正常樣式。
此順序對於重要樣式是反向的。所有未分層的重要樣式級聯到一個隱式層中,該層優先於所有非過渡正常樣式。未分層的重要樣式具有低於任何重要分層樣式的優先順序。在早期宣告的層中的重要樣式優先於同一來源中後續宣告的層中的重要樣式。
對於本教程的其餘部分,我們將把討論限制在作者樣式,但請記住層也可以存在於使用者和使用者代理樣式表中。
級聯層可以解決的問題
大型程式碼庫可能包含來自多個團隊、元件庫、框架和第三方的樣式。無論包含多少樣式表,所有這些樣式都以單個來源級聯在一起:作者樣式表。
將來自許多來源的樣式級聯在一起,尤其是來自不協同工作的團隊的樣式,可能會產生問題。不同的團隊可能有不同的方法;一個團隊的最佳實踐可能是降低特異性,而另一個團隊的標準可能是在每個選擇器中包含一個 id。
特異性衝突可能會迅速升級。Web 開發人員可能會透過新增 !important 標誌來建立“快速修復”。雖然這可能看起來是一個簡單的解決方案,但它通常只是將特異性戰爭從正常宣告轉移到重要宣告。
就像級聯來源在使用者、使用者代理和作者樣式之間提供了一種權力平衡一樣,級聯層提供了一種結構化的方式來組織和平衡單個來源內的關注點,就好像來源中的每個層都是一個子來源。可以為每個團隊、元件和第三方建立一個層,樣式的優先順序基於層順序。
層內的規則級聯在一起,而不會與層外的樣式規則競爭。級聯層能夠優先處理整個樣式表而不是其他樣式表,而無需擔心這些子來源之間的特異性。
層優先順序總是勝過選擇器特異性。具有優先順序的層中的樣式“勝過”優先順序較低的層。失敗層中選擇器的特異性無關緊要。特異性對於層內的競爭屬性值仍然很重要,但層之間沒有特異性問題,因為只考慮每個屬性的最高優先順序層。
巢狀級聯層可以解決的問題
級聯層允許建立巢狀層。每個級聯層都可以包含巢狀層。
例如,可以將元件庫匯入到 components 層中。常規級聯層會將元件庫新增到作者來源,從而消除與任何其他作者樣式的特異性衝突。在 components 層中,開發人員可以選擇定義各種主題,每個主題都作為一個單獨的巢狀層。這些巢狀主題層的順序可以根據媒體查詢(參見下面的層建立和媒體查詢部分)來定義,例如視口大小或方向。這些巢狀層提供了一種建立主題的方式,它們不會基於特異性發生衝突。
巢狀層的功能對於任何從事元件庫、框架、第三方小部件和主題開發的人來說都非常有用。
建立巢狀層的功能也消除了對層名稱衝突的擔憂。我們將在巢狀層部分介紹這一點。
“作者可以建立層來表示元素預設值、第三方庫、主題、元件、覆蓋和其他樣式關注點——並且能夠以明確的方式重新排序層的級聯,而無需更改每個層內的選擇器或特異性,也無需依賴出現順序來解決層間的衝突。”
—級聯和繼承規範。
建立級聯層
可以使用以下任一方法建立層
@layer宣告 at-rule,使用@layer後跟一個或多個層的名稱來宣告層。這會建立命名層,而無需為其分配任何樣式。@layer塊 at-rule,其中塊內的所有樣式都新增到命名或未命名層中。- 帶
layer關鍵字或layer()函式的@import規則,它將匯入檔案的內容分配到該層中。
如果尚未初始化具有該名稱的層,則所有三種方法都會建立一個層。如果 @layer at-rule 或帶有 layer() 的 @import 中未提供層名稱,則會建立一個新的匿名(未命名)層。
注意:層的優先順序順序是它們被建立的順序。不在層中或“未分層樣式”的樣式級聯到一個最終的隱式標籤中。
在討論巢狀層之前,讓我們更詳細地介紹建立層這三種方式。
用於命名層的 @layer 宣告 at-rule
層的順序由它們在 CSS 中出現的順序設定。使用 @layer 後跟一個或多個層的名稱而不分配任何樣式來宣告層是定義層順序的一種方式。
@layer CSS at-rule 用於宣告級聯層並在存在多個級聯層時定義優先順序順序。以下 at-rule 聲明瞭三個層,按列出的順序
@layer theme, layout, utilities;
您通常希望將此 @layer 宣告(當然,層名稱對您的站點有意義)作為 CSS 的第一行,以完全控制層排序。
如果以上語句是站點 CSS 的第一行,則層順序將為 theme、layout 和 utilities。如果在此語句之前建立了一些層,只要這些名稱的層尚不存在,這三個層將被建立並新增到現有層列表的末尾。但是,如果具有相同名稱的層已經存在,則以上語句將只建立兩個新層。例如,如果 layout 已經存在,則只建立 theme 和 utilities,但在這種情況下,層的順序將為 layout、theme 和 utilities。
用於命名層和匿名層的 @layer 塊 at-rule
可以使用塊 @layer at-rule 建立層。如果 @layer at-rule 後跟一個識別符號和一個樣式塊,則該識別符號用於命名該層,並且此 at-rule 中的樣式將新增到該層的樣式中。如果具有指定名稱的層尚不存在,則將建立一個新層。如果具有指定名稱的層已經存在,則樣式將新增到先前存在的層中。如果在使用 @layer 建立樣式塊時未指定名稱,則 at-rule 中的樣式將新增到新的匿名層中。
在下面的示例中,我們使用了四個 @layer 塊 at-rule 和一個 @layer 宣告 at-rule。此 CSS 按列出的順序執行以下操作
- 建立一個名為
layout的層 - 建立一個未命名、匿名層
- 宣告一個包含三個層的列表,並且只建立兩個新層,
theme和utilities,因為layout已經存在 - 向已有的
layout層新增額外的樣式 - 建立第二個未命名、匿名層
/* file: layers1.css */
/* unlayered styles */
body {
color: #333333;
}
/* creates the first layer: `layout` */
@layer layout {
main {
display: grid;
}
}
/* creates the second layer: an unnamed, anonymous layer */
@layer {
body {
margin: 0;
}
}
/* creates the third and fourth layers: `theme` and `utilities` */
@layer theme, layout, utilities;
/* adds styles to the already existing `layout` layer */
@layer layout {
main {
color: black;
}
}
/* creates the fifth layer: an unnamed, anonymous layer */
@layer {
body {
margin: 1vw;
}
}
在上述 CSS 中,我們按順序建立了五個層:layout、<anonymous(01)>、theme、utilities 和 <anonymous(02)>,以及一個包含在 body 樣式塊中的第六個隱式未分層樣式層。層的順序是層建立的順序,未分層樣式的隱式層始終在最後。一旦建立,就無法更改層順序。
我們將一些樣式分配給名為 layout 的層。如果命名層尚不存在,則在 @layer at-rule 中指定名稱,無論是否將樣式分配給該層,都會建立該層;這會將該層新增到現有層名稱系列的末尾。如果命名層已經存在,則命名塊內的所有樣式都將附加到先前存在的層中的樣式——透過重用現有層名稱在塊中指定樣式不會建立新層。
匿名層是透過在不命名層的情況下將樣式分配給層來建立的。樣式只能在其建立時新增到未命名層中。
注意:後續使用不帶層名稱的 @layer 會建立額外的未命名層;它不會將樣式附加到先前存在的未命名層。
@layer at-rule 建立一個層(無論是否命名),或者如果命名層已經存在,則將樣式附加到該層。我們將第一個匿名層稱為 <anonymous(01)>,第二個稱為 <anonymous(02)>,這只是為了方便解釋。這些實際上是未命名的層。無法引用它們或向它們新增額外的樣式。
所有在層之外宣告的樣式都組合在一個隱式層中。在上面的示例程式碼中,第一個宣告將 color: #333333 屬性設定在 body 上。這在任何層之外宣告。即使未分層樣式具有較低的特異性並且在出現順序中排在第一位,正常的未分層宣告也優先於正常的已分層宣告。這解釋了為什麼即使未分層 CSS 在程式碼塊中首先宣告,包含這些未分層樣式的隱式層也優先,就好像它是最後一個宣告的層一樣。
在 @layer theme, layout, utilities; 這一行中,聲明瞭一系列層,只建立了 theme 和 utilities 層;layout 已在第一行中建立。請注意,此宣告不會更改已建立層的順序。目前無法在聲明後重新排序層。
在以下示例中,我們將樣式分配給兩個層,並在過程中建立並命名它們。由於它們已經存在,在第一次使用時建立,因此在最後一行宣告它們沒有任何作用。
<h1>Is this heading underlined?</h1>
@layer page {
h1 {
text-decoration: overline;
color: red;
}
}
@layer site {
h1 {
text-decoration: underline;
color: green;
}
}
/* this does nothing */
@layer site, page;
嘗試將最後一行 @layer site, page; 移動到第一行。會發生什麼?
層建立和媒體查詢
如果您使用媒體或功能查詢定義層,並且媒體不匹配或功能不受支援,則不會建立該層。下面的示例展示了更改裝置或瀏覽器的大小可能會如何更改層順序。在此示例中,我們只在較寬的瀏覽器中建立 site 層。然後,我們按順序將樣式分配給 page 和 site 層。
<h1>Is this heading underlined?</h1>
@media (width >= 50em) {
@layer site;
}
@layer page {
h1 {
text-decoration: overline;
color: red;
}
}
@layer site {
h1 {
text-decoration: underline;
color: green;
}
}
在寬屏上,site 層在第一行宣告,這意味著 site 的優先順序低於 page。否則,site 優先於 page,因為它在窄屏上稍後宣告。如果不起作用,請嘗試將媒體查詢中的 50em 更改為 10em 或 100em。
使用 @import 將樣式表匯入命名層和匿名層
@import 規則允許使用者將樣式規則從其他樣式表直接匯入到 CSS 檔案或 <style> 元素中。
匯入樣式表時,@import 語句必須定義在樣式表或 <style> 塊中的任何 CSS 樣式之前。@import 語句必須排在第一位,在任何樣式之前,但可以緊跟在建立了一個或多個層但沒有為這些層分配任何樣式的 @layer at-rule 之後。(@import 也可以緊跟在 @charset 規則之後。)
您可以將樣式表匯入到命名層、巢狀命名層或匿名層中。以下層分別將樣式表匯入到 components 層、components 層內的巢狀 dialog 層以及未命名層中
@import "components-lib.css" layer(components);
@import "dialog.css" layer(components.dialog);
@import "marketing.css" layer();
您可以將多個 CSS 檔案匯入到單個層中。以下宣告將兩個單獨的檔案匯入到單個 social 層中
@import "comments.css" layer(social);
@import "sm-icons.css" layer(social);
您可以使用媒體查詢和功能查詢根據特定條件匯入樣式和建立層。以下程式碼僅在瀏覽器支援 display: ruby 並且匯入的檔案取決於螢幕寬度時,才將樣式表匯入到 international 層。
@import "ruby-narrow.css" layer(international) supports(display: ruby)
(width < 32rem);
@import "ruby-wide.css" layer(international) supports(display: ruby)
(width >= 32rem);
注意:沒有等效的 <link> 方法來連結樣式表。當您無法在樣式表中使用 @layer 時,請使用 @import 將樣式表匯入到層中。
巢狀級聯層概述
巢狀層是命名層或匿名層內的層。每個級聯層,即使是匿名層,也可以包含巢狀層。匯入到另一個層中的層成為該層中的巢狀層。
巢狀層的優勢
巢狀層的功能使團隊能夠建立級聯層,而無需擔心其他團隊是否會將其匯入到層中。同樣,巢狀使您能夠將第三方樣式表匯入到層中,而無需擔心該樣式表本身是否具有層。由於層可以巢狀,因此您不必擔心外部和內部樣式表之間存在衝突的層名稱。
建立巢狀級聯層
巢狀層可以使用與常規層相同的方法建立。例如,可以使用 @layer at-rule 後跟一個或多個層名來建立,並使用點表示法。多個點和層名錶示多層巢狀。
如果您將塊 @layer at-rule 巢狀在另一個塊 @layer at-rule 中,無論是否帶名稱,巢狀的塊都將成為一個巢狀層。同樣,當使用包含 layer 關鍵字或 layer() 函式的 @import 宣告匯入樣式表時,樣式將被分配給該命名或匿名層。如果 @import 語句包含層,則這些層將成為該匿名或命名層內的巢狀層。
我們來看看下面的例子
@import "components-lib.css" layer(components);
@import "narrow-theme.css" layer(components.narrow);
在第一行中,我們將 components-lib.css 匯入到 components 層。如果該檔案包含任何層,無論是命名層還是未命名層,這些層都將成為 components 層中的巢狀層。
第二行將 narrow-theme.css 匯入到 narrow 層,這是 components 的子層。巢狀的 components.narrow 將作為 components 層中的最後一個層建立,除非 components-lib.css 已經包含一個 narrow 層,在這種情況下,narrow-theme.css 的內容將附加到 components.narrow 巢狀層。可以使用模式 components.<layerName> 將其他巢狀命名層新增到 components 層。如前所述,可以建立未命名層,但隨後無法訪問它們。
我們來看另一個例子,其中我們使用以下語句將 layers1.css 匯入到命名層中
@import "layers1.css" layer(example);
這將建立一個名為 example 的單層,其中包含一些宣告和五個巢狀層——example.layout、example.<anonymous(01)>、example.theme、example.utilities 和 example.<anonymous(02)>。
要向命名巢狀層新增樣式,請使用點表示法
@layer example.layout {
main {
width: 50vw;
}
}
根據層順序確定優先順序
層的順序決定了它們的優先順序順序。因此,層的順序非常重要。就像級聯按來源和重要性進行排序一樣,級聯也按來源層和重要性對每個 CSS 宣告進行排序。
常規級聯層的優先順序順序
@import "A.css" layer(firstLayer);
@import "B.css" layer(secondLayer);
@import "C.css";
上面的程式碼建立了兩個命名層(C.css 樣式附加到未分層樣式的隱式層)。讓我們假設這三個檔案(A.css、B.css 和 C.css)內部不包含任何其他層。以下列表顯示了這些檔案內部和外部宣告的樣式將從最低(1)優先順序到最高(10)優先順序進行排序。
firstLayer正常樣式(A.css)secondLayer正常樣式(B.css)- 未分層正常樣式(
C.css) - 行內正常樣式
- 動畫樣式
- 未分層重要樣式(
C.css) secondLayer重要樣式(B.css)firstLayer重要樣式(A.css)- 行內重要樣式
- 過渡樣式
層內宣告的普通樣式優先順序最低,並按層建立的順序排序。第一個建立的層中的普通樣式優先順序最低,最後一個建立的層中的普通樣式在這些層中優先順序最高。換句話說,如果存在任何衝突,firstLayer 中宣告的普通樣式將被列表中任何後續樣式覆蓋。
接下來是任何在層外宣告的樣式。C.css 中的樣式未匯入到層中,並將覆蓋來自 firstLayer 和 secondLayer 的任何衝突樣式。未在層中宣告的樣式始終比在層中宣告的樣式具有更高的優先順序(重要樣式除外)。
內聯樣式使用 style 屬性宣告。以這種方式宣告的正常樣式將優先於在未分層和分層樣式表(firstLayer – A.css、secondLayer – B.css 和 C.css)中找到的正常樣式。
動畫樣式具有比所有正常樣式(包括內聯正常樣式)更高的優先順序。
重要樣式,即包含 !important 標誌的屬性值,優先於我們列表中先前提到的任何樣式。它們按正常樣式的相反順序排序。在層外宣告的任何重要樣式比在層內宣告的樣式優先順序低。層內找到的重要樣式也按層建立的順序排序。對於重要樣式,最後建立的層具有最低優先順序,而第一個建立的層在宣告的層中具有最高優先順序。
行內重要樣式再次具有比在其他地方宣告的重要樣式更高的優先順序。
過渡樣式具有最高優先順序。當正常屬性值正在過渡時,它優先於所有其他屬性值宣告,甚至行內重要樣式;但僅在過渡期間。
<div>
<h1 style="color: yellow; background-color: maroon !important;">
Inline styles
</h1>
</div>
@layer A, B;
h1 {
font-family: sans-serif;
margin: 1em;
padding: 0.2em;
color: orange;
background-color: green;
text-decoration: overline pink !important;
box-shadow: 5px 5px lightgreen !important;
}
@layer A {
h1 {
color: grey;
background-color: black !important;
text-decoration: line-through grey;
box-shadow: -5px -5px lightblue !important;
font-style: normal;
font-weight: normal !important;
}
}
@layer B {
h1 {
color: aqua;
background: yellow !important;
text-decoration: underline aqua;
box-shadow: -5px 5px magenta !important;
font-style: italic;
font-weight: bold !important;
}
}
在此示例中,最初使用不帶任何樣式的 @layer 語句 at-rule 定義了兩個層(A 和 B)。層樣式在兩個 @layer 塊 at-rule 中定義,這些 at-rule 出現在任何層之外宣告的 h1 CSS 規則之後。
使用 style 屬性在 h1 元素上新增的行內樣式設定了正常的 color 和重要的 background-color。正常的行內樣式會覆蓋所有分層和未分層的正常樣式。重要的行內樣式會覆蓋所有分層和未分層的正常和重要的作者樣式。作者樣式無法覆蓋重要的行內樣式。
正常的 text-decoration 和重要的 box-shadow 不屬於 style 行內樣式,因此可以被覆蓋。對於正常的非行內樣式,未分層樣式具有優先順序。對於重要樣式,層順序也很重要。雖然正常的未分層樣式會覆蓋層中設定的所有正常樣式,但對於重要樣式,優先順序順序是相反的;未分層的重要樣式比分層樣式具有更低的優先順序。
僅在層內宣告的兩種樣式是 font-style(正常重要性)和 font-weight(帶有 !important 標誌)。對於正常樣式,最後宣告的 B 層會覆蓋早期宣告的 A 層中的樣式。對於正常樣式,後面的層優先於前面的層。優先順序順序對於重要樣式是反向的。對於重要的 font-weight 宣告,首先宣告的 A 層優先於最後宣告的 B 層。
您可以透過將第一行從 @layer A, B; 更改為 @layer B, A; 來反轉層順序。試一試。哪些樣式會因此改變,哪些保持不變?為什麼?
層的順序由它們在 CSS 中出現的順序設定。在我們的第一行中,我們使用 @layer 後跟層名稱聲明瞭層,但沒有分配任何樣式,以分號結尾。如果省略了這一行,結果也會相同。為什麼?我們按 A 然後 B 的順序在命名的 @layer 塊中分配了樣式規則。這兩個層是在第一行中建立的。如果它們沒有被建立,這些規則塊也會以該順序建立它們。
我們包含第一行有兩個原因:首先,您可以輕鬆編輯該行並切換順序;其次,通常您會發現預先宣告層順序是層順序管理的最佳實踐。
總結
- 層的優先順序順序是層被建立的順序。
- 一旦建立,就無法更改層順序。
- 正常樣式的層優先順序是層建立的順序。
- 未分層正常樣式優先於正常分層樣式。
- 重要樣式的層優先順序是相反的,早期建立的層具有優先順序。
- 所有分層的重要樣式都優先於未分層的重要(和正常)樣式。
- 正常內聯樣式優先於所有正常樣式,無論是否分層。
- 重要內聯樣式優先於所有其他樣式,正在過渡的樣式除外。
- 作者樣式無法覆蓋重要的行內樣式(除了臨時過渡它們)。
巢狀級聯層的優先順序順序
巢狀層的級聯優先順序順序與常規層相似,但包含在層內。優先順序順序基於巢狀層建立的順序。層中的非巢狀樣式優先於巢狀的正常樣式,而重要樣式的優先順序順序則相反。巢狀層之間的特異性權重無關緊要,但對於巢狀層內的衝突樣式則很重要。
以下程式碼建立並向 components 層、components.narrow 巢狀層和 components.wide 巢狀層新增樣式
div {
background-color: wheat;
color: pink !important;
}
@layer components {
div {
background-color: yellow;
border: 1rem dashed red;
color: orange !important;
}
}
@layer components.narrow {
div {
background-color: skyblue;
border: 1rem dashed blue;
color: purple !important;
border-radius: 50%;
}
}
@layer components.wide {
div {
background-color: limegreen;
border: 1rem dashed green;
color: seagreen !important;
border-radius: 20%;
}
}
以下是所使用的屬性以及每個宣告應用原因的摘要
background-color:因為未分層正常樣式優先於分層正常樣式,所以wheat顏色勝出。border:因為在一個層內,非巢狀樣式優先於正常巢狀樣式,所以red顏色勝出。color:對於重要樣式,分層樣式優先於未分層樣式,其中在早期宣告的層中的重要樣式優先於在後期宣告的層。在此示例中,巢狀層建立的順序是components.narrow,然後是components.wide,因此components.narrow中的重要樣式優先於components.wide中的重要樣式,這意味著purple顏色勝出。border-radius:屬性僅在巢狀層中設定,因此按宣告順序20%半徑勝出。
總結
如果您理解了本文的大部分內容,那麼恭喜您——您現在已熟悉 CSS 級聯層的基本機制。