文件結構選擇器
CSS 文件結構選擇器是非常基本的選擇器,除了可以利用 HTML 文件結構的親子關係選取元素,也能透過子代選擇器「>」、兄弟選擇器「~」或相鄰兄弟選擇器「+」的交互應用,快速找到 HTML 文件裡的特定元素,這篇教學會介紹 CSS 文件結構選擇器。
快速導覽:
HTML 文件結構的親子關係
HTML 是個層層包覆的「樹狀結構」,在樹狀結構裡,處於外層的元素稱作「父元素」,內層元素稱為「子元素」,父元素和子元素是一個「相對關係」,在身為別人的父元素的同時,可能也是另外一個元素的子元素,然而除了父元素和子元素,還有「子孫元素」、「祖先元素」和「兄弟元素」...等相對元素,而 CSS 文件結構選擇器也就會根據 HTML 的結構,選取到對應的元素。
下圖呈現一個簡單的 HTML 樹狀結構:
後代選擇器 ( 空白分隔 )
後代選擇器撰寫時「由左到右」列出每一代元素,元素之間使用「空白」分隔,並選取「最右側」的元素,此處的空白稱之為「結合子 combinator」,意思為「是...的一部分」,下方展示基本的撰寫方式:
p a {color: red;} /* 選取 p 元素裡的「所有 a 元素」 */
nav ul li em a {color: red;} /* 選取 nav 元素裡的 ul 元素裡的 li 元素裡的「所有 em 元素」 */
除了單純使用元素名稱,也可以搭配 id、class 或屬性等其他選擇器使用,不過因為 id 選擇器有其特殊性,通常會擺在最前方或獨立撰寫,下方的寫法,會選取 id 為 oxxo 的元素裡 class 為 fruit 元素裡的「所有 a 元素」。
#oxxo .class a {color: red;}
如果搭配通用選擇器「*
」,就能泛指下一層「所有的」元素,下方的寫法,會將 div 裡所有的元素 ( 不包含 div 自己 ),不論在哪一層,都會變成紅色文字。
div * {color: red;}
下方的網頁有五個超連結 a 元素在 ul 清單元素裡,也有另外一個 a 元素在 footer 元素中,雖然一開始透過 CSS 元素選擇器定義了所有 a 的樣式為綠色文字,但擺在清單裡的 a 元素利用了 CSS 後代選擇器定義樣式,由於使用三個元素選擇器,權重變成「0-0-3」,所呈現的樣式就會是紅色文字。
<!-- HTML 程式碼 -->
<ul>
<li><a href="http://oxxo.studio">oxxo.studio</a></li>
<li><a href="https://steam.oxxostudio.tw">STEAM</a></li>
<li><a href="https://www.google.com">Google</a></li>
<li><a href="https://www.apple.com">Apple</a></li>
<li><a href="https://www.github.io">Github</a></li>
</ul>
<footer>
<a href="about.html">about us</a>
</footer>
<!-- CSS 程式碼 -->
<style>
a {color: green;} /* 所有 a 的文字都是綠色,權重 0-0-1 */
ul li a {color: red;} /* ul 裡的 li 裡的所有 a 都是紅色,權重 0-0-3 */
</style>
子代選擇器 ( > )
有別於後代選擇器,子代選擇器只會選擇「下一層元素」( 也就是「兒子」概念 ),子代選擇器使用「>
」符號分隔,>
前後可以加上空白,加上的空白不具任何意義。例如下方的寫法,會選取 p 元素裡的「下一層 a 元素」。
p > a {color: red;}
因為 >
是選取「子元素」,如果位於「下一層之後」的元素,就不會被選取,例如下方網頁執行後,前兩個 a 元素位在第一層是子元素,所以會變成紅色,而後兩個 a 位在第四層,屬於後代元素,所以就會呈現綠色。
<!-- HTML 程式碼 -->
<nav>
<a href="http://oxxo.studio">oxxo.studio</a>
<br/>
<a href="https://steam.oxxostudio.tw">STEAM</a>
<div>
<a href="https://www.google.com">Google</a>
<br/>
<a href="https://www.apple.tw">Apple</a>
</div>
</nav>
<!-- CSS 程式碼 -->
<style>
a {color: green;} /* 所有 a 的文字都是綠色 */
nav > a {color: red;} /* nav 的子元素 a 是紅色 */
</style>
子代選擇器也可以搭配 class 選擇器和屬性選擇器,做出更多的組合,但因為 id 選擇器有其特殊性,通常會擺在最前方或獨立撰寫,不會穿插在結構選擇器裡,例如下方的寫法,只有 div 子元素具有指定的 class 名稱或屬性才會變色。
<!-- HTML 程式碼 -->
<div>
<h2>oxxo.studio</h2>
<span>
<em class="name">oxxo</em>
</span>
<h3 class="name">hello world!!</h3>
<h3 name="oxxo">Good morning!!</h3>
</div>
<!-- CSS 程式碼 -->
<style>
.name {color: gray;} /* 所有 .name 都是灰色,權重 0-1-0 */
div > .name {color: red;} /* div 子元素的 .name 為紅色,權重 0-1-1 */
div > [name="oxxo"] {color: orange;} /* div 子元素屬性 name 為 oxxo 的元素為橘色,權重 0-1-1 */
</style>
不過如果搭配通用選擇器「*
」時,則需要特別注意!因為通用選擇器泛指「下層所有元素」,所以使用後不會只有下一層,而是所有的後代都會被選取!
<!-- HTML 程式碼 -->
<ul>
<li>
<span><em>我應該不會變色吧?</em></span>
</li>
<li>
<span> <em>想太多了,一定變色的呀</em></span>
</li>
</ul>
<!-- CSS 程式碼 -->
<style>
ul > * {color: red;}
</style>
兄弟選擇器 ( ~ )
兄弟選擇器表示「同一層並位於後方的特定元素」,兄弟選擇器使用「~
」符號分隔,~
前後可以加上空白,加上的空白不具任何意義。例如下方的寫法,會選取所有跟 h2 元素「同一層且位於後方」的 a 元素。
題外話,如果以中文文法來說,應該要叫「弟妹選擇器」,而不是「兄弟選擇器」。
h2 ~ a {color: red;}
因為 ~
是選取「同一層且位於後方的元素」,如果位於「其他層」或「位於前方」的元素,就不會被選取,例如下方網頁執行後,只有跟 h2 同層且在後方的 a 元素會變成紅色,其他層的 a 元素以及在 h2 前方的 a 元素則會呈現綠色。
<!-- HTML 程式碼 -->
<nav>
<a href="#">因為我在 h2 前面,所以我是綠色~</a>
<h2>OXXO.STUDIO</h2>
<a href="http://oxxo.studio">oxxo blog</a>
<br/>
<a href="https://steam.oxxostudio.tw">STEAM</a>
<div>
<a href="https://www.google.com">Google</a>
<br/>
<a href="https://www.apple.tw">Apple</a>
</div>
</nav>
<!-- CSS 程式碼 -->
<style>
a {color: green;} /* 所有 a 的文字都是綠色 */
h2 ~ a {color: red;} /* 跟 h2 同層且位於後方的 a 是紅色 */
</style>
兄弟選擇器也可以搭配通用選擇器「*
」,搭配後就會選擇「同一層且位於後方的所有元素」,其行為和和搭配子元素選擇器不同,使用時要特別注意!以下方網頁為例,網頁開啟後,跟 h2 同層且位於 h2 後方的所有元素都會變成紅色,但在其他層的元素以及位於 h2 前方的元素就不會變色。
<!-- HTML 程式碼 -->
<nav>
<a href="https://www.google.com">因為我在 h2 前方,所以我不會變色</a>
<h2>OXXO.STUDIO</h2>
<a href="http://oxxo.studio">oxxo blog</a>
<div>
<a href="https://www.google.com">我不會變色</a>
<br/>
</div>
<h3>我應該不會變色吧?</h3>
<h4>你一定變色的呀!</h4>
<span>天呀我變色啦!</span>
</nav>
<!-- CSS 程式碼 -->
<style>
a {color: green;} /* 所有 a 的文字都是綠色 */
h2 ~ * {color: red;} /* 跟 h2 同層且位於後方的所有元素都是紅色 */
</style>
相鄰兄弟選擇器 ( + )
相鄰兄弟選擇器表示「同一層的後一個元素」,相鄰兄弟選擇器使用「+
」符號分隔,+
前後可以加上空白,加上的空白不具任何意義。例如下方的寫法,會選 h2 元素「同一層且下一個」的 a 元素。
h2 + a {color: red;}
因為 +
是選取「同一層的下一個元素」,如果位於「其他層」或「不屬於下一個」的元素,就不會被選取,例如下方網頁執行後,只有跟 h2 同層且下一個的 a 元素會變成紅色,其他所有的 a 元素則會呈現綠色。
<!-- HTML 程式碼 -->
<div>
<a>我不會變色</a>
<h2>OXXO.STUDIO</h2>
<a>我會變色</a>
<br/>
<a>我不會變色哇哈哈</a>
<ul>
<li><a>我也不會變色</a></li>
<li><a>我也不會變色</a></li>
</ul>
</div>
<!-- CSS 程式碼 -->
<style>
h2 + a {color: red;}
</style>
如果選取的下一個元素「不是指定的元素」,就會找不到元素,例如下方範例中下個元素是 h3 而不是 a,就不會套用任何樣式,最後就會呈現全部都是黑色文字的狀況。
<!-- HTML 程式碼 -->
<div>
<a>我不會變色</a>
<h2>OXXO.STUDIO</h2>
<h3>我會變色嗎?</h3>
<a>我會變色嗎?</a>
<br/>
<a>我不會變色哇哈哈</a>
<ul>
<li><a>我也不會變色</a></li>
<li><a>我也不會變色</a></li>
</ul>
</div>
<!-- CSS 程式碼 -->
<style>
h2 + a {color: red;}
</style>
如果使用通用選擇器「*
」搭配相鄰兄弟選擇器,作用的範圍就是選取「同層的下一個任意元素」,不論下一個元素是誰,選到了就會變色,如果將下方的 CSS 套用到剛剛的網頁,就會發現 h3 變成了紅色文字。
h2 + * {color: red;} /* 選取同層的下一個任意元素 */
小結
文件結構選擇器是一個很方便的選擇器,可以在不撰寫任何 id、class 或屬性的狀況下,快速選擇特定的元素,而相關的選取技術不僅限於 CSS,許多爬蟲語法也都使用結構樹的方式進行選取,因此這是必學的選取器喔。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~