CSS選擇器允許你通過型別、屬性、位於HTML檔案中的位置來選擇元素。本教學闡述了三個新選項
:is()
、:where()
和:has()
。
選擇器通常在樣式表中使用。下面的範例會找到所有<p>
段落元素並將字重更改為粗體:
p {
font-weight: bold;
}
你也可以在JavaScript中使用選擇器來找到DOM節點:
偽類選擇器根據HTML元素的當前狀態來定位它們。也許最廣為人知的是 :hover
,它在遊標移到一個元素上時應用樣式,所以它被用來高亮可點選的連結和按鈕。
其他受歡迎的選項包括:
:visited
:匹配存取過的連結:target
:匹配檔案URL所指向的元素:first-child
:指向第一個子元素:nth-child
:選擇指定子元素:empty
:匹配沒有內容或子元素的元素:checked
:匹配已勾選的核取方塊或無線電鈕:blank
:選擇使用者輸入為空的輸入框:enabled
:匹配一個被啟用的輸入框。如果一個元素能夠被啟用(如選擇、點選或接受文字輸入),或者能夠獲取焦點,則該元素是啟用的:disabled
:匹配一個被禁用的輸入框。在被禁用時,元素不能被啟用或獲取焦點:required
:指向必填的輸入框。所謂必填,就是在提交所屬表單之前,使用者必須為輸入框指定一個值:valid
:匹配一個內容驗證正確的輸入框:invalid
:匹配一個內容未通過驗證的輸入框:playing
:指向一個正在播放的audio
或video
元素瀏覽器最近又收到了三個偽類選擇器…
注意:這最初被指定為:matches()
和:any()
,但:is()
已經成為CSS標準。
MDN解釋::is()
CSS偽類函數將選擇器列表作為引數,並選擇該列表中任意一個選擇器可以選擇的元素。這對於以更緊湊的形式編寫大型選擇器非常有用。
你經常需要在不止一個元素上面應用相同的樣式。比如說,<p>
段落文字顏色預設為黑色,但是當它位於<article>
,<section>
,<aside>
裡面時,文字顏色為灰色:
/* default black */
p {
color: #000;
}
/* gray in <article>, <section>, or <aside> */
article p,
section p,
aside p {
color: #444;
}
這是一個簡單的例子,但更復雜的頁面將導致更復雜和更冗長的選擇器字串。任何選擇器的語法錯誤都會破壞所有元素的樣式。
像Sass這樣的CSS前處理器允許巢狀(這也將出現在原生CSS中)。
article, section, aside {
p {
color: #444;
}
}
這可以建立相同的CSS程式碼,減少打字的工作量,並可以防止錯誤。但是:
:is()
提供了一個原生CSS解決方案。該特性已被所有現代瀏覽器支援(IE除外)。
:is(article, section, aside) p {
color: #444;
}
單個選擇器可以包含任意數量的:is()
偽類。比如說,下面的複雜選擇器將綠色文字顏色應用於所有<h1>
、<h2>
和<p>
元素,這些元素是<section>
的子元素,其包含類.primary
或.secondary
,並且不是<article>
的第一個子元素。
article section:not(:first-child):is(.primary, .secondary) :is(h1, h2, p) {
color: green;
}
沒有 :is()
的同等程式碼需要六個CSS選擇器。
article section.primary:not(:first-child) h1,
article section.primary:not(:first-child) h2,
article section.primary:not(:first-child) p,
article section.secondary:not(:first-child) h1,
article section.secondary:not(:first-child) h2,
article section.secondary:not(:first-child) p {
color: green;
}
注意,:is()
無法匹配::before
和::after
偽元素,因此下面範例程式碼會不起作用:
/* NOT VALID - selector will not work */
div:is(::before, ::after) {
display: block;
content: '';
width: 1em;
height: 1em;
color: blue;
}
:where()
選擇器語法與:is()
相同,也被所有現代瀏覽器支援(IE除外)。這往往會導致相同的樣式。比如:
:where(article, section, aside) p {
color: #444;
}
不同點在於優先順序。優先順序是用來決定哪個CSS選擇器應該覆蓋所有其他選擇器的演演算法。在下面的例子中,article p
比單獨的p
更加具體,因此所有位於<article>
內的p
元素的字型顏色將會是灰色:
article p { color: #444; }
p { color: #000; }
在:is()
的情況下,優先順序是在其引數中找到的最具體的選擇器。在:where()
的情況下,優先順序為零。
考慮下面的CSS:
article p {
color: black;
}
:is(article, section, aside) p {
color: red;
}
:where(article, section, aside) p {
color: blue;
}
讓我們將這個CSS應用到下面的HTML中:
<article>
<p>paragraph text</p>
</article>
段落文字將被渲染為紅色,點選連結檢視CodePen範例。
:is()
選擇器與article p
具有相同的優先順序,但它在樣式表的後面,所以文字變成了紅色。如有必要可以同時刪除article p
和:is()
選擇器來應用藍色,因為:where()
選擇器的優先順序比兩者都低。
更多的程式碼庫會使用:is()
而不是:where()
。然而,:where()
的零優先順序對CSS重置來說是很實用的,它在沒有特定樣式的情況下應用標準樣式的基線。通常情況下,重置會應用一個預設的字型、顏色、內邊距和外邊距。
這個CSS重置程式碼對<h2>
標題應用了1em
的上外邊距,除非它們是<article>
元素的首個子元素。
/* CSS reset */
h2 {
margin-block-start: 1em;
}
article :first-child {
margin-block-start: 0;
}
試圖在樣式表的後面設定一個自定義的<h2>
上外邊距是沒有效果的,因為article :first-child
有更高的優先順序:
/* never applied - CSS reset has higher specificity */
h2 {
margin-block-start: 2em;
}
你可以用一個更高優先順序的選擇器來解決這個問題,但這需要更多的程式碼,而且對其他開發者來說不併不明顯。你最終會忘記你為什麼需要它。
/* styles now applied */
article h2:first-child {
margin-block-start: 2em;
}
你也可以通過對每個樣式應用!important
來解決這個問題,但請避免這樣做!它使進一步的樣式定義和開發變得更具挑戰性。
/* works but avoid this option! */
h2 {
margin-block-start: 2em !important;
}
一個更好的選擇是在你的CSS重置中採用:where()
的零優先順序。
/* reset */
:where(h2) {
margin-block-start: 1em;
}
:where(article :first-child) {
margin-block-start: 0;
}
現在,你可以覆蓋任何CSS重置樣式,無論其優先順序如何;不需要進一步的選擇器或!important
:
/* now works! */
h2 {
margin-block-start: 2em;
}
:has()
選擇器使用了類似於:is()
和:where()
的語法,但它的目標是一個包含其他元素的元素。比如說,這裡是為任何包含一個或多個<img>
或<section>
標籤的<a>
連結新增藍色、兩畫素寬的邊框的CSS:
/* style the <a> element */
a:has(img, section) {
border: 2px solid blue;
}
這是幾十年來最激動人心的CSS進展!開發者們終於有了一種針對父元素的方法。
難以捉摸的"父選擇器"一直是人們請求最多的CSS特性之一,但它給瀏覽器供應商帶來了效能上的麻煩。因此,它已經即將到來了很長時間。簡而言之:
<body>
標籤為止。假設供應商已經解決了效能問題,:has()
的引入允許過去沒有JavaScript就不可能實現的成為可能。例如,當任何必填的內部欄位沒有校驗通過時,你可以設定外部表單<fieldset>
和下面的提交按鈕的樣式。
/* red border when any required inner field is invalid */
fieldset:has(:required:invalid) {
border: 3px solid red;
}
/* change submit button style when invalid */
fieldset:has(:required:invalid) + button[type='submit'] {
opacity: 0.2;
cursor: not-allowed;
}
這個例子新增了一個導航連結子選單指示器,其中包含一個子選單項的列表:
/* display sub-menu indicator */
nav li:has(ol, ul) a::after {
display: inlne-block;
content: ">";
}
或者,你可以新增偵錯樣式,比如高亮顯示所有沒有內部img
的<figure>
元素。
/* where's my image?! */
figure:not(:has(img)) {
border: 3px solid red;
}
在開啟你的編輯器和重構你的CSS程式碼庫之前,請注意:has()
是很新的,支援比:is()
和:where()
更有限。它在Safari 15.4+和Chrome 105+可用,但是到2023年應該可以廣泛使用。
:is()
和 :where()
偽類選擇器簡化了 CSS 語法。你對巢狀和CSS前處理器的需求會減少。
:has()
更具革命性和令人激動。父級選擇將迅速流行起來,我們將忘記黑暗時代。
以上就是本文的所有內容,如果對你有所幫助,歡迎點贊收藏轉發~