級聯、繼承、權重與選擇器

理解樣式的最終決策

級聯

CSS 的 C 就是代表著級聯 Cascade 的意思,可以把它想成等級的概念,如下範例:

/* 等級 1 */
h1 {
    color: red;
}

/* 等級 2 */
h1 span {
    color: green;
}

/* 等級 3 */
h1 span span{
    color: yellow;
}

在之後的選擇器我們會再更近一步的說明,目前只要知道級聯的意義即可,而近期新推出的級聯層 Cascade Layer 是更進階的技術,在章節五的管理裡會再介紹。

我們即將進入 CSS 的核心概念,從這裡開始該打起精神學習囉!

在相同級聯、相同權重的情況下,最後定義的會是最終樣式,如下範例:

/* 這個範例的結果,會是套用綠色文字。 */

h1 {
    color: red;
}

h1 {
    color: green;
}

繼承

Inheritance,就有如字面意思,直接將父母親層級的樣式沿用,即稱為繼承,如下範例:

在這個範例中,<body> 已經有設定文字為藍色,所以他的子元素們都會繼承他的文字顏色,直到 <span> 又再次設定文字顏色為黑色。

注意,CSS 屬性有些會繼承,有些不會繼承,例如寬度。 您可以在查詢屬性時,查看他的繼承欄位,例如 MDN 的 color 屬性介紹頁的定義區塊就有明確列出這個屬性是否可以繼承。

選擇器

其實我們已經使用過選擇器了,在這個篇幅我們會更近一步的學習更多的選擇器用法。

所謂的 CSS 選擇器,就是在 CSS 檔案內撰寫我們要「指定某個對象」樣式的這件事情,例如:

<main>
    <p>
        <h1 id="main-title" class="main-title2" title="main-title3">這是標題</h1>
    </p>
</main>

如果我們要對 <h1> 做樣式的話,我們至少有以下這些樣式可以執行:

/* 標籤選擇器 */
h1 {
    color: red;
}

/* 層疊選擇器,權重較高,層疊越多越耗效能 */
main p h1 {
    color: red;
}

/* id 選擇器 */
#main-title {
    color: red;
}

/* class 選擇器 */
.main-title2 {
    color: red;
}

/* 屬性選擇器 */
[title="main-title3"] {
    color: red;
}

/* 偽元素,常見為 :before 與 :after */
h1:before {
    content: '在「這是標題」前插入文字';
    color: red;
}

/*
偽類,又分為動態、結構、迴圈、表單 4 類
此範例為當滑鼠滑在 h1 上時,改變 h1 顏色。
*/
h1:hover {
    color: red;
}


/* 您也可以混合使用 */
#main-title.main-title2 {
    color: red;
}

id 與 class 不能以數字開頭命名!

也不可以全部都是數字!

在多個標籤與混合使用的範例,您會發現前者有空格,後者無空格,這是 CSS 的定義,說明如下:

/* 有空格:代表選擇其子元素,例如在此範例中,p 是 main 的子元素,h1 是 main 和 p 的子元素 */
main p h1 {
    color: red;
}

/*
無空格:會使用在 id、class、屬性,通常用來選擇相同元素但賦予其不同樣式(但不是同一個元素)。
也就是說此範例是要選擇 id 是 main-title 且 classname 是 main-title2 的 <h1>
*/
h1#main-title.main-title2 {
    color: red;
}

接下來我們還要針對比較特別的選擇器進一步說明。

通用選擇器

/* 選擇全部 */
* {
    color: red;
}

/* 選擇 <p> 的第一層子分類中的 <h1> */
p > h1 {
    color: red;
}

/* <p> 「之後」的「第一個」相鄰的<h2>元素,改變 <h2> 的文字顏色 */
p + h2 {
    color: red;
}

/* <p> 「之後」的「所有」相鄰的<h2>元素,改變 <h2> 的文字顏色 */
p ~ h2 {
    color: red;
}

屬性選擇器

我們可以在 HTML 元素上加上已經被定義的屬性或是自行添加的屬性:

<p title="already-define" data-my-custom="my-custom-a">自行定義 attribute</p>
<p title="already-define" data-my-custom="my-custom-b">自行定義 attribute<

所以以下兩種寫法都可以得到相同的樣式結果:

[title="already-define"] {
    color: red;
}

[data-my-custom="my my-custom-a"] {
    color: red;
}

[data-my-custom="my my-custom-b"] {
    color: red;
}

在上例中,要完全等於才有辦法套用樣式,但在實務上,通常我們會有基本型與其延伸出的變化型需求,所以屬性選擇器還可以有更多樣的選擇方式:


/* 只要有 data-my-custom 就套用 */
[data-my-custom] {
    color: red;
}

/* 完全等於 my-custom-a 才套用 */
[data-my-custom="my-custom-a"] {
    color: red;
}

/* data-my-custom 開頭等於 my- 就套用 */
[data-my-custom^="my-"] {
    color: red;
}

/* data-my-custom 結尾等於 -a 就套用 */
[data-my-custom^="-a"] {
    color: red;
}

/* data-my-custom 值只要有出現 my- 就套用 */
[data-my-custom*="my-"] {
    color: red;
}

/* data-my-custom 值包含 my 就套用,但是以單字判斷 */
[data-my-custom~="my"] {
    color: red;
}

/* data-my-custom 值以 my 或 my- 開頭就套用 */
[data-my-custom|="my"] {
    color: red;
}

偽類、偽元素選擇器

因為太多了,所以不一一列舉,您可以至 w3school 觀看所有偽類偽元素的選擇器。

權重

在某些形況下,我們會希望由一個基礎樣式擴充出不同樣式,我們可以使用這樣的方式撰寫:

main p h1 {
    color: red;
}

/* 在 <h1> 多加一個 class="change-title-colo" */
main p h1.change-title-color {
    color: green;
}

<h1> 會先找到紅色,之後又找到綠色,然後判斷綠色為最終樣式進而應用。為什麼會判斷綠色為最終樣式呢?

CSS 的最終樣式,取決於其重要的程度。在元素當中,我們可以為其增加 id 與 class 屬性,在 CSS 當中則有各式選擇器、偽類、!important、inline style 會影響權重,總的來說,可以下圖來表示重要程度:

可以將權重分成五個數字,其構成為 !important - inline style - id - class - element,越左邊代表重要程度越大。例如:h1 + p::first-letter 可分成 h1、p、與 ::first-letter,而這三個都是屬於最右邊的數字所以就會是 0-0-0-0-3。

而 *、+、>、~ 和否定則不影響權重。

如果我們 CSS 寫錯了,或是瀏覽器不支援, 該 CSS 將會被忽略,也就是不管它,當作沒有這一個東西存在,也就不會算進去權重裡。 通常我們會利用工具來檢驗沒有使用到/沒有作用的 CSS 以提高效能。

小結

善用選擇器將會讓效能、維護性、可讀性、易用性提高非常多,請務必練習各種選擇器的方式。

作業

線上有很多 CSS 選擇器的遊戲網站挑戰看看,增強選擇的功力。

參考來源

Last updated