首頁 > web前端 > css教學 > 更多現實世界的用途:has()

更多現實世界的用途:has()

Christopher Nolan
發布: 2025-03-09 11:51:12
原創
242 人瀏覽過

More Real-World Uses for :has()

CSS 的 :has() 偽類無疑是我最喜歡的 CSS 新特性之一,相信許多 State of CSS 調查參與者也認同這一點。這種“倒置”選擇器的能力賦予了我們意想不到的強大功能。

之所以說是“更強大的功能”,是因為許多聰明的開發者已經發表了許多令人驚嘆的巧妙想法,例如:

  • Jen Simmons 的《使用 :has() 作為 CSS 父選擇器及更多》
  • Bramus 的《使用 CSS :has() 實現針對具有相同類別的“元素島”的數量查詢》
  • Bramus 的《根據子元素數量設置父元素樣式》
  • Manuel Matuzović 的《在 :has() 中使用組合器》
  • Austin Gil 的《CSS :has() 讓你的 HTML 表單更出色的四種方法》
  • Zoran Jambor 的《視頻::has() 偽類的實用案例》
  • Jhey Tompkins 的《:has():家族選擇器》

本文並非 :has() 的權威指南,也不是對現有內容的重複。我只是想分享一些我在日常工作中最可能使用 :has() 的方法……當然,前提是瀏覽器支持足夠好。 (Firefox 是最後一個堅持不懈的瀏覽器,但即將支持它。)

一旦瀏覽器支持完善,我肯定會在各個地方使用 :has()。以下是一些我最近構建的真實案例,當時我心想:“一旦 :has() 得到完全支持,這將會變得多麼簡潔!”

避免在 JavaScript 組件外部進行操作

你是否曾經構建過一個交互式組件,有時需要影響頁面其他地方的樣式?以下示例中,<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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板