iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Modern Web

前端迷走中:從零開始的新手之路系列 第 19

[Day 19] 選擇不障礙,讓CSS幫你──複合選擇器、複雜選擇器跟選擇器列表

  • 分享至 

  • xImage
  •  

昨天我們提到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;
}

組合器與複雜選擇器

除了andor,也可以依據HTML元素的層級關係,來組合多個選擇器的條件。

在CSS中,這樣的層級關係由組合器(Combinator)來表示。

基本的組合器有四種,包括描述上下層級關係的後代組合器、子代組合器,以及描述同一層級關係的後續手足組合器以及下個手足組合器。

將多個選擇器以組合器相隔放在一起,會合成一個複雜選擇器(Complex selector)。[1]

後代組合器

在CSS選擇器的語法中,空格 代表的是後代組合器(Descendant combinator)。

後代組合器表示的元素關係,如果以血親的概念來理解,就是直系血親的關係。不論彼此之間是幾親等。

以下圖片中,<ul>元素以及其下的三個<li>元素都是<div>元素的後代元素。

Descendant

圖片來源:Selectutorial - CSS selectors

如果想要挑選<ul><li>元素的內容,可以<div>作為基準,使用元素選擇器搭配後代組合器,組成一個複雜選擇器。

像是div ul,就會選到<div>元素底下的<ul>元素。不過因為三個<li>都存在於<ul>之中,所以用這個複雜選擇器設定樣式時,可能就會一併套用到底下的<li>元素。

如果只要將樣式套用到底下的三個<li>,可以跳過<ul>,使用div li這個複雜選擇器。

子代組合器

與後代組合器類似的是,大於符號>代表的子代組合器(Child combinator)。

相比後代組合器,子代組合器表示的元素關係更為限縮。如果以血親的概念來理解,就是一親等的直系血親。

以下圖片中,只有<ul>元素是<div>元素的子代元素。

Child

圖片來源:Selectutorial - CSS selectors

所以可以使用div > ul來篩選這個<ul>元素的內容;
但無法使用div > li來篩選這些<li>元素的內容,因為<ul>底下的三個<li>元素跟<div>元素是二親等的直系血親。

後續手足組合器

除了上下的層級關係,也有表示同層級關係的組合器。像是波浪號~代表的後續手足組合器(The subsequent-sibling combinator)。

後續手足組合器表示的關係,如果以血親來理解,就是作為旁系二等血親的所有弟弟妹妹。

以下圖片中,左邊的<div>元素有<h1><p><p><hr>等子元素。如果從左至右將這些子元素排行,以最左邊的<h1>作為長子,那其他的子元素都是<h1>的弟弟妹妹。

Sibling

圖片來源: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>&lt;q&gt;跟&lt;blockquote&gt;的差別</h3>
      <p>.........</p>
      <h3>預設樣式</h3>
      <p>.........</p>
      <h3>引用來源</h3>
      <h3 class="example">範例</h3>
      <section class="example">
        <p>
          以下由MDN提供的例子,使用&lt;figcaption&gt;描述引文的出處,並使用&lt;cite&gt;來表示書名:
        </p>
        <p>.........</p>
      </section>
    </section>
  </article>
  <footer>
    <p class="keyword">
      Tags:
      <span>引文</span>、<span>程式碼</span>、<span>&lt;span&gt;</span>、<span
        >&lt;div&gt;</span
      >
    </p>
  </footer>

以及最終呈現的結果:
https://ithelp.ithome.com.tw/upload/images/20251004/20116445FF2Yja2Ds9.png

複合選擇器

複合選擇器方面,做了三組對比。

同一種元素,分成不同類別

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


上一篇
[Day 18] 選擇不障礙,讓CSS幫你──元素、類別、ID 與通用選擇器
下一篇
[Day 20] 選擇不障礙,讓CSS幫你──屬性選擇器
系列文
前端迷走中:從零開始的新手之路21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言