CSS最新的強大 :has() 父層選取器來了!
: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