高級 CSS 選擇器指南,你學會了嗎?
一、基礎選擇器
在說高級選擇器之前,先來回顧一下CSS中的基礎選擇器。
1. 元素選擇器
最常見的 CSS 選擇器就是元素選擇器。選擇器通常將是某個 HTML 元素:
h1 {
color: red;
font-size: 50px;
}
在 W3C 標準中,元素選擇器又稱為類型選擇器(type selector)。類型選擇器匹配文檔語言元素類型的名稱。類型選擇器匹配文檔樹中該元素類型的每一個實例。
2. ID 選擇器
id 選擇器用來指定具有ID的元素的樣式。ID 選擇器前面有一個 # 號 - 也稱為棋盤號或井號。
#my_id {
color: red;
font-size: 50px;
}
需要注意,在一個 HTML 文檔中,ID 選擇器會使用一次,而且僅一次。并且 ID 選擇器不能結合使用,因為 ID 屬性不允許有以空格分隔的詞列表。
3. 類選擇器
CSS類選擇器會根據元素的類屬性中的內容匹配元素。類屬性被定義為一個以空格分隔的列表項,在這組類名中,必須有一項與類選擇器中的類名完全匹配,此條樣式聲明才會生效。類選擇器也是我們最常用的選擇器之一。
.my_class {
color: red;
font-size: 50px;
}
二、通配選擇器
在CSS中,一個星號(*)就是一個通配選擇器,之所以如此命名,是因為它普遍適用于所有元素,可以匹配任意類型的HTML元素。那通配符選擇器有啥實際應用呢?其會常用于全局樣式重置,比如 CSS 盒子模型重置:
*,
*::before,
*::after {
box-sizing: border-box;
}
這意味著我們希望所有元素在盒子模型計算中包括padding和border,而不是將這些寬度添加到任何定義的尺寸。例如,在以下規則中,.box寬度將是200px,而不是200px + 20px:
.box {
width: 200px;
padding: 10px;
}
三、屬性選擇器
CSS 屬性選擇器通過已經存在的屬性名或屬性值匹配元素。這是一個非常強大的選擇器,但是通常沒有充分發揮其潛力。CSS 屬性選擇器可以獲得類似于正則表達式的匹配結果。這對于修改 BEM 風格的系統或其他使用相關類名但可能不是單個通用類名的框架非常有用。來看一個例子:
[class*="component_"]
這個選擇器將選擇所有具有包含 component_ 字符串的類的元素。
可以通過在關閉屬性選擇器之前包含 i 來確保匹配不區分大小寫:
[class*="component_" i]
當然我們也可以不指定屬性值,而是簡單的檢查它是否存在,例如下面的選擇器會選擇具有任何class值 的所有 a 標簽:
a[class]
屬性選擇器可以用來執行一些基本的可訪問性檢查,例如:
img:not([alt]) {
outline: 2px solid red;
}
這將為所有不包含 alt 屬性的圖像添加輪廓。
四、子代選擇器
當使用 > 選擇符分隔兩個元素時,它只會匹配那些作為第一個元素的直接后代(子元素)的第二元素。子組合選擇器是唯一處理元素級別的選擇器,并且可以組合以選擇嵌套元素。
? 選擇 article > p
<article>
<p>Hello world</p>
</article>
?? 未選擇 article > p
<article>
<blockquote>
<p>Hello world</p>
</blockquote>
</article>
有一個側邊欄導航列表,從語義上講,這會是一個包含 li 元素的 ul 元素列表。我們可能希望頂層鏈接的樣式與嵌套鏈接的樣式不同。要僅針對頂級鏈接,可以使用以下選項:
nav > ul > li > a {
font-weight: bold;
}
五、通用兄弟選擇器
兄弟選擇符,位置無須緊鄰,只需同層級,A~B 選擇A元素之后所有同層級B元素。
例如,p~img 將為位于段落后面某個位置的所有圖像設置樣式,前提是它們屬于同一個父元素:
<article>
<p>Paragraph</p>
<h2>Headline 2</h2>
<img src="img.png" alt="Image" />
<h3>Headline 3</h3>
<img src="img.png" alt="Image" />
</article>
將通用兄弟選擇器與有狀態偽類選擇器(如:checked)相結合,可以產生有趣的效果。復選框的HTML結構如下:
<input id="terms" type="checkbox" />
<label for="terms">terms</label>
只有選中復選框之后下面的樣式才會生效:
#terms:checked ~ p {
font-style: italic;
color: #797979;
}
六、相鄰兄弟選擇器
相鄰兄弟選擇器 (+) 介于兩個選擇器之間,當第二個元素_緊跟在_第一個元素之后,并且兩個元素都是屬于同一個父元素的子元素,則第二個元素將被選中。
當我們想給一個列表之間添加間隙時,最常用的方式是給每個元素添加一個外邊距,但是這樣就還需要去除第一個元素的外邊距。我們可以使用相鄰兄弟選擇器來協助添加外邊距:
nav ul li + li {
margin-left: 2rem;
}
這樣就可以在列表項之間產生間隙效果,而無需在第一個項目上清除額外的邊距。
除此之外,我們還可以使用相鄰兄弟選擇器方便得給label標簽和表單標簽之間添加間隙:
label + input {
margin-left: 10px;
}
七、偽類選擇器
CSS 偽類是添加到選擇器的關鍵字,指定要選擇的元素的特殊狀態。這些極大地增強了 CSS 的功能,并啟用了過去經常被錯誤地歸入 JavaScript 的功能。
下面這些偽類選擇器是有狀態的:選擇器是有狀態的:
- :focus
- :hover
- :visited
- :target
- :checked
以下選擇器依賴于元素順序:
- :nth-child()、:nth-of-type()
- :first-child、:first-of-type
- :last-child、:last-of-type
- :only-child、:only-of-type
還有一些非常有用的偽類比如:not(),新支持的偽類:is(),以及隨著 CSS 自定義屬性(變量)的支持而出現在偽類:root。
nth系列的選擇器有著很多應用,比如想實現一個交投背景色的表格,就可以使用nth-child選擇器,使用even(偶數行)或者odd(奇數行)關鍵字即可:
tbody tr:nth-child(odd) {
background-color: #ddd;
}
效果如下:
當然也可以自己指定間隔規則:
li:nth-child(3n + 1) {
background-color: rebeccapurple;
}
這將第一個元素開始,每隔每三個元素選一個:
我們可以使用:not()選擇器從選擇器中排除元素,上面我們就使用a:not([class])來定位沒有應用class的鏈接。我們可以鏈接:not()選擇器使用,如果想為表單字段輸入創建規則,但不是某些類型就可以這樣寫:
input:not([type="hidden"]):not([type="radio"]):not([type="checkbox"])
也可以在:not()中包含其他偽類選擇器,例如排除:disabled狀態的按鈕:
button: not(: disabled);
八、偽元素選擇器
偽元素是一個附加至選擇器末的關鍵詞,允許對被選擇元素的特定部分修改樣式。它們在應用中差異很大,目前最受支持的偽元素選擇器如下:
- ::after
- ::before
- ::first-letter
- ::first-line
- ::selection
::before 和 ::after 偽元素可以用來創建一個額外的元素,它們在視覺上似乎是DOM的一部分,但不是真正的HTMLDOM的一部分。由于它們的行為類似于真實元素,所以在使用flexbox或grid布局時,它們會被計算為子元素,這大大增強了它們的功能。
在使用::before 和 ::after之前需要了解兩個重要的概念:
- 在使其可見之前需要設置content屬性,此屬性可以設置為空字符串;
- 一般情況下,::before將顯示在主元素內容之前,而::after將顯示在其之后。
默認情況下,它們的行為類似于內聯元素:
當給段落添加 display:flex 之后的效果如下:
切換為display:grid的效果如下:
我們可以使用偽元素::selection來定義選中文本的樣式:
::selection {
background: yellow;
color: black;
}