昨天我們提到CSS有四種基本的選擇器,包括元素選擇器、類別選擇器、ID選擇器,以及通用選擇器。
這些選擇器還能組合在一起使用,同時以多個條件篩選網頁中的內容,就像是合體變成新的選擇器一樣。
如果要挑選同時符合多個選擇器條件的內容,可以將這些選擇器彼此相接放在一起,達成類似and
的效果。
例如以下範例挑選的內容,除了需要是<section>
元素之外,class
的屬性值還需要包括example
。
section.example {
border: 5px dotted;
}
如此,即便有些內容有同樣的class
屬性值,仍然可以透過他們不一樣的地方去區別彼此。可能是元素種類,也可能是另外的屬性值。
這些選擇器相接在一起,就像是合成一個新的選擇器。稱作複合選擇器(Compound selector)。[1]
需要注意的是,如果複合選擇器中包含通用選擇器或元素選擇器,則通用選擇器或元素選擇器只能放在開頭,且只能出現在複合選擇器一次。
與and
相對的是or
。
如果將多個選擇器以逗號,
相隔放在一起,則挑選出的內容只需要符合其中一個選擇器的條件。這類似於or
的效果。例如以下範例:
h1,
h2,
h3 {
font-family: "Noto Sans TC", serif;
}
選擇器以逗號相隔放在一起,會組成一個選擇器列表(Selector list )。[1]
這麼做可以精簡我們的程式碼。例如以下由MDN提供的例子,以重複的程式碼對<span>
跟<div>
元素設定了同樣的樣式:
span {
border: red 2px solid;
}
div {
border: red 2px solid;
}
這時候就可以將這些選擇器以逗號組成一個選擇器列表,以一條規則宣告共同的樣式:
span, div {
border: red 2px solid;
}
在選擇器列表中,逗號前後可以加上空格。也可以在不同選擇器間換行,讓程式碼更好閱讀:[2]
span,
div {
border: red 2px solid;
}
需要注意的是,只要有一個選擇器無效,則整個選擇器列表的規則都會無效。[2]
以下由MDN提供的範例,類別選擇器..special
以兩個點開頭,語法上有錯誤。如此一來,不只是..special
本身會無效,整個列表都會無效。所以<h1>
元素也不會套用樣式。
h1, ..special {
color: blue;
}
除了and
或or
,也可以依據HTML元素的層級關係,來組合多個選擇器的條件。
在CSS中,這樣的層級關係由組合器(Combinator)來表示。
基本的組合器有四種,包括描述上下層級關係的後代組合器、子代組合器,以及描述同一層級關係的後續手足組合器以及下個手足組合器。
將多個選擇器以組合器相隔放在一起,會合成一個複雜選擇器(Complex selector)。[1]
在CSS選擇器的語法中,空格
代表的是後代組合器(Descendant combinator)。
後代組合器表示的元素關係,如果以血親的概念來理解,就是直系血親的關係。不論彼此之間是幾親等。
以下圖片中,<ul>
元素以及其下的三個<li>
元素都是<div>
元素的後代元素。
圖片來源:Selectutorial - CSS selectors
如果想要挑選<ul>
或<li>
元素的內容,可以<div>
作為基準,使用元素選擇器搭配後代組合器,組成一個複雜選擇器。
像是div ul
,就會選到<div>
元素底下的<ul>
元素。不過因為三個<li>
都存在於<ul>
之中,所以用這個複雜選擇器設定樣式時,可能就會一併套用到底下的<li>
元素。
如果只要將樣式套用到底下的三個<li>
,可以跳過<ul>
,使用div li
這個複雜選擇器。
與後代組合器類似的是,大於符號>
代表的子代組合器(Child combinator)。
相比後代組合器,子代組合器表示的元素關係更為限縮。如果以血親的概念來理解,就是一親等的直系血親。
以下圖片中,只有<ul>
元素是<div>
元素的子代元素。
圖片來源:Selectutorial - CSS selectors
所以可以使用div > ul
來篩選這個<ul>
元素的內容;
但無法使用div > li
來篩選這些<li>
元素的內容,因為<ul>
底下的三個<li>
元素跟<div>
元素是二親等的直系血親。
除了上下的層級關係,也有表示同層級關係的組合器。像是波浪號~
代表的後續手足組合器(The subsequent-sibling combinator)。
後續手足組合器表示的關係,如果以血親來理解,就是作為旁系二等血親的所有弟弟妹妹。
以下圖片中,左邊的<div>
元素有<h1>
、<p>
、<p>
、<hr>
等子元素。如果從左至右將這些子元素排行,以最左邊的<h1>
作為長子,那其他的子元素都是<h1>
的弟弟妹妹。
圖片來源:Selectutorial - CSS selectors
如果想要挑選最右邊的<hr>
,可以將<h1>
作為基準,使用元素選擇器搭配後續手足組合器,組成h1 ~ hr
這樣的複雜選擇器。
即便中間隔著其他的弟弟妹妹<p>
,h1 ~ hr
還是可以選得到<hr>
。
與後續手足組合器類似的,是由加號+
代表的下個手足組合器(The next-sibling combinator)。
下個手足組合器表示的關係,如果以血親來比喻,就是下一個弟弟或妹妹。
延續剛剛的例子,如果要透過下個手足組合器挑選最右邊的<hr>
,就無法以<h1>
作為基準,因為<h1>
的下個手足是<p>
。
如果要繼續使用下個手足組合器來挑選<hr>
,必須改以第二個<p>
作為基準,組成p ~ hr
這樣的複雜選擇器。
雖然這樣的複雜選擇器沒有限定是由哪一個<p>
作為基準,但確實有個<hr>
是某個<p>
的下個手足元素,所以還是可以挑選出<hr>
。
接下來,實際來練習看看,怎麼將不同選擇器組合在一起使用吧。
以下是網頁內容的HTML程式碼。
<body>
<article>
<h1>[Day 16] 暫別 HTML──引文、程式碼與通用容器</h1>
<p>
前幾天提到怎麼在網頁中加入<span class="keyword yesterday">連結</span
>、<span class="keyword yesterday">清單</span>、<span
class="keyword yesterday"
>表格</span
>跟<span class="keyword yesterday">圖片</span>。
</p>
<section class="content">
<h2 id="h2-1">引文</h2>
<h3><q>跟<blockquote>的差別</h3>
<p>.........</p>
<h3>預設樣式</h3>
<p>.........</p>
<h3>引用來源</h3>
<h3 class="example">範例</h3>
<section class="example">
<p>
以下由MDN提供的例子,使用<figcaption>描述引文的出處,並使用<cite>來表示書名:
</p>
<p>.........</p>
</section>
</section>
</article>
<footer>
<p class="keyword">
Tags:
<span>引文</span>、<span>程式碼</span>、<span><span></span>、<span
><div></span
>
</p>
</footer>
以及最終呈現的結果:
複合選擇器方面,做了三組對比。
section.example {
border: 5px dotted;
}
section.content {
border: 5px solid;
}
文章介紹引文的部分,包在一個section
元素裡,class
屬性值設為content
。
引文的section
內,又將介紹範例的部分以另一個section
包起來,class
屬性值設為example
。
雖然兩者都是section
,但在元素選擇器後面接著類別選擇器,組成不同的複合選擇器。
section.content
的邊框設為實線;section.example
的邊框則設成點狀。
section.example {
border: 5px dotted;
}
h3.example {
text-decoration: underline;
}
雖然範例的內容區塊與標題的class
屬性值都是example
,但兩者屬於不同種類的元素。於是以元素選擇器搭配類別選擇器,組成不同的複合選擇器。
section.example
將邊框設為虛線;h3.example
則是將標題「範例」畫上底線。
.keyword {
font-weight: bold;
}
.keyword.yesterday {
color: blue;
}
昨日關鍵字,與文章底下的標籤,class屬性值都包括keyword
,於是以類別選擇器將文字設為粗體。
但昨日關鍵字的class屬性值同時還包括yesterday
,於是將兩個類別選擇器組合在一起,將昨日關鍵字的文字設為藍色。
h1,
h2,
h3 {
font-family: "Noto Sans TC", serif;
}
不同層級的標題,字體都要設為"Noto Sans TC", serif
。
於是將三個元素選擇器以逗號相隔,組成一個選擇器列表,同時設定三種標題的字體。
article p {
font-family: "Noto Sans TC", sans-serif;
}
article > p {
background-color: grey;
}
文章前言的<p>
,沒有另外以<section>
包起來;
其他內容的<p>
,則另外放在代表不同部分的<section>
裡。
由於文章內文的字體都要設為"Noto Sans TC", sans-serif;
,於是用後代組合器將兩個元素選擇器組合在一起;
前言的部分為了做出區別,則另外以子代組合器,將背景顏色設為灰色。
h2 ~ h3 {
font-style: italic;
}
h2 + h3 {
color: red;
}
h2 ~ h3
因為是用後續手足組合器,於是把次標標題「引文」後面的小標題都設為斜體;h2 + h3
則因為是使用下個手足組合器,所以只有把次標標題後面的第一個小標題「<q>
跟<blockquote>
的差別」設為紅色。
今天介紹了將選擇器搭配在一起使用的方法。
包括將選擇器相接放在一起,組成複合選擇器。
還有將選擇器以逗號相隔放在一起,組成選擇器列表。
以及將選擇器以表示元素層級關係的組合器分隔,放在一起,組成複雜選擇器。
不過,CSS還有其他種類的選擇器值得介紹。
但時間不多了,讓我們下集待續~
[1]: CSS selector structure - CSS | MDN
[2]: Basic CSS selectors