CSS 的 :has()
偽類無疑是我最喜歡的 CSS 新特性之一,相信許多 State of CSS 調查參與者也認同這一點。這種“倒置”選擇器的能力賦予了我們意想不到的強大功能。
之所以說是“更強大的功能”,是因為許多聰明的開發者已經發表了許多令人驚嘆的巧妙想法,例如:
本文並非 :has()
的權威指南,也不是對現有內容的重複。我只是想分享一些我在日常工作中最可能使用 :has()
的方法……當然,前提是瀏覽器支持足夠好。 (Firefox 是最後一個堅持不懈的瀏覽器,但即將支持它。)
一旦瀏覽器支持完善,我肯定會在各個地方使用 :has()
。以下是一些我最近構建的真實案例,當時我心想:“一旦 :has()
得到完全支持,這將會變得多麼簡潔!”
你是否曾經構建過一個交互式組件,有時需要影響頁面其他地方的樣式?以下示例中,<nav></nav>
是一個 mega 菜單,打開它會更改上方內容的顏色。
我覺得我總是需要做這種事情。
這個具體的例子是我為一個網站製作的 React 組件。我不得不使用 document.querySelector(...)
“觸及”頁面的 React 部分之外,並在 <header></header>
、<main></main>
或其他組件上切換一個類。這並非世界末日,但感覺確實有點彆扭。即使在一個完全的 React 網站(例如 Next.js 網站)中,我也必須在管理更高組件樹上的 menuIsOpen
狀態或執行相同的 DOM 元素選擇之間做出選擇——這不太符合 React 的風格。有了 :has()
,問題就解決了:
header:has(.megamenu--open) { /* 如果包含具有类“.megamenu--open”的元素,则以不同的方式设置 header 样式 */ }
我的 JavaScript 組件不再需要處理 DOM 的其他部分了!
為表格添加交替的行“條紋”可以改善用戶體驗。它們可以幫助你的眼睛在掃描表格時跟踪當前所在的行。
但根據我的經驗,這在只有兩三行的表格上效果不佳。例如,如果你的表格在 <tbody> 中有三行,並且你對每“偶數”行進行“條紋”處理,你最終可能只有一條條紋。這並不值得採用這種模式,並且可能會讓用戶疑惑那一個高亮顯示的行有什麼特別之處。使用 Bramus 使用 <code>:has()
根據子元素數量應用樣式的技術,我們可以在有超過三行時應用表格條紋:
想要更高級的功能?你還可以決定只有在表格至少有特定數量的列時才執行此操作:
header:has(.megamenu--open) { /* 如果包含具有类“.megamenu--open”的元素,则以不同的方式设置 header 样式 */ }
我經常需要根據頁面上的內容更改頁面佈局。以以下網格佈局為例,主要內容的位置會根據是否存在側邊欄而更改網格區域。
這可能取決於 CMS 中是否設置了同級頁面。我通常會使用模板邏輯來有條件地向佈局包裝器添加 BEM 修飾符類,以適應這兩種佈局。該 CSS 可能如下所示(為簡潔起見,省略了響應式規則和其他內容):
table:has(:is(td, th):nth-child(3)) { /* 只有在有三列或更多列时才执行操作 */ }
當然,從 CSS 的角度來看,這完全沒問題。但這確實使模板代碼有點混亂。根據你的模板語言,有條件地添加一堆類可能會變得非常難看,尤其是在你必須對許多子元素也這樣做的情況下。
將其與基於 :has()
的方法進行對比:
/* m = 主要内容 */ /* s = 侧边栏 */ .standard-page--with-sidebar { grid-template-areas: 's s s m m m m m m m m m'; } .standard-page--without-sidebar { grid-template-areas: '. m m m m m m m m m . .'; }
老實說,從 CSS 的角度來看,這並沒有好多少。但在我看來,從 HTML 模板中移除條件修飾符類是一個不錯的收穫。
很容易想到 :has()
的微型設計決策——例如,當卡片中包含圖像時——但我認為它對於這些宏觀佈局更改也非常有用。
如果你閱讀過我之前的文章,你會知道我是一個特異性方面的堅持者。如果你像我一樣,不希望在整個樣式中添加 :has()
和 :not()
時特異性分數激增,請務必使用 :where()
。
這是因為 :has()
的特異性基於其參數列表中最具體的元素。因此,如果你在其中包含類似 ID 的內容(我不知道為什麼!),你的選擇器將很難在級聯中被覆蓋。
另一方面,:where()
的特異性始終為零,永遠不會增加特異性分數。
/* m = 主要内容 */ /* s = 侧边栏 */ .standard-page:has(.sidebar) { grid-template-areas: 's s s m m m m m m m m m'; } .standard-page:not(:has(.sidebar)) { grid-template-areas: '. m m m m m m m m m . .'; }
這些只是我迫不及待想要在生產環境中使用的一些功能。 CSS-Tricks Almanac 也提供了一些示例。你期待用 :has()
做什麼?你遇到過哪些 :has()
將是完美解決方案的真實案例?
以上是更多現實世界的用途:has()的詳細內容。更多資訊請關注PHP中文網其他相關文章!