css :has 偽類 父層選擇器

CSS最新的強大 :has() 父層選取器來了!

王淳藝 Celia Wang 2022/12/05 14:34:49
12105

:has() 偽類是個非常好用的選取器,能夠做到許多原本需要使用 JS 才能達到的事,他的規範在很久之前就有制定,但是礙於瀏覽器性能的影響一直沒有被支援,直到今年 2022 ,隨著 Safari 開始支援 :has() 的使用,未來各大瀏覽器跟著開放支援也只是時間的問題,所以是時候來認識這個強大的工具了!

----

1. :has() 偽類的用法

在CSS中,偽類是添加到選擇器的關鍵字,用於指定所選元素的特殊狀態。

用白話文來說,就是指:若某元素匹配某選擇器,就可以讓它做到某些我們指定要它做的事情。

以下舉出一些簡單好理解的例子:

 

a:has(img) { display: block; }

這個例子表示,如果有任何<a>元素裡面包含<img>的話,則這個<a>元素會吃到 display: block; 的樣式。

 

除了可以直接選取 tag 之外,:has() 也支援所有的 CSS 字符,以下用 > 舉個例子:

a:has(> img) { display: block; }

這個例子表示,如果有任何<a>元素裡面有直接的子元素<img>的話,則這個<a>元素會吃到 display: block; 的樣式,那如果<a>只是有其他非直接子元素的更遠後代包含<img>的話就不會發揮作用。

 

再來,:has()也支援複雜選擇器,例如:

article:has(h5, p) { background-color: #f0f3f9; }

這個例子表示,假設有<article>元素當中包含了 <h5> <p>,則該<artical>背景色會變為 #f0f3f9。

那如果想要的選擇條件從變為呢?那就改為這樣:

article:has(h5):has(p) { background-color: #f0f3f9; }

這樣的寫法就會變為,同時包含了<h5>與<p>的<article>才會改變背景色。

 

以上舉了少數幾個 :has() 能夠使用的寫法,那麼當實際使用時可以怎麼運用呢?接著來舉例運用場景。

 

 

2. :has() 偽類的運用

元素表單必填欄位加上 "*"

<form>
  <item>
    <label>用戶名</label>
    <input required>
  </item>
  <item>
    <label>備註</label>
    <input>
  </item>
</form>

這時我們可以利用 :has() 來幫第一個輸入條件加上必填的星號:

label:has(+input:required)::before{
  content: '*';
  color: red;
}

在這邊我們運用了 "+" 來指定與<label>同層級的第一個順位,且有 ":required" 條件的<input>,讓符合以上條件的 input 的 label 加上一個 ::before 偽元素來製作紅色的 "*"。

如果是以前的做法,可能會需要將要加上必填符號的<label>另外加上新的 class name 之類的,那使用 :has() 就不需要這麼麻煩。

 

 

• Navbar 子選項 hover 時改變 <body> 背景色

從這個架構我們得到了三個基本選項的 navbar:

<nav class="menu">
  <a href="#" class="L1">選項1</a>
  <a href="#" class="L2">選項2</a>
  <a href="#" class="L3">選項3</a>
</nav>

現在我們想讓每個選項 hover 時,整個<body>背景色都會隨著改變成三種不同的顏色,我們可以這麼做:

*這邊先略過基本的 Menu 樣式設定,直接切入重點敘述如何讓選項  hover  時改變整個 <body> 的色彩*

body:has(.L1:hover) {
  background-color: #3f7fab;
}
body:has(.L2:hover) {
  background-color: #9b6acf;
}
body:has(.L3:hover) {
  background-color: #57936d;
}  

 

可以看到上面的 CSS 寫法就是利用 :has() 讓 .L1 .L2 .L3 hover 時,<body>去做個別情境下的換色,就這麼簡單!

但以往想做到這樣子的效果,會需要使用到 JS ,現在只要短短幾行就可以在 CSS 解決了,是不是很值得歡呼!

 

 

3. :has() 偽類的瀏覽器支援度

目前 :has() 在瀏覽器的支援度上還不是那麼廣泛,但是相信在未來一年的時間,一定會更加普及,到時候就可以隨心所欲地使用了。

以上就是淺談 :has() 這個超好用的 CSS 新神器介紹,是不是也覺得相見恨晚呢!馬上筆記起來吧~~~

 

----

參考資料:

https://www.readfog.com/a/1680107683889385472

https://www.zhangxinxu.com/wordpress/2022/08/css-has-pseudo-class/

https://rizkicitra.dev/blog/css-has

王淳藝 Celia Wang