跳至主要内容

[CSS] Efficient CSS

keywords: css, refactor

:is() 和 :where

:is() @ MDN

範例一

/* 原本的寫法 */
article h2, article h3, article h4, article h5 {
font-weight: bold;
font-family: sans-serif;
}

使用 :is()(過去曾經稱作 :matches():any())來改寫:

/* 更好的寫法 */
article :is(h2, h3, h4, h5) {
font-weight: bold;
font-family: sans-serif;
}

範例二

/* CREDIT: ttps://developer.mozilla.org/en-US/docs/Web/CSS/:is */

/* 原本的寫法 */
header p:hover,
main p:hover,
footer p:hover {
color: red;
cursor: pointer;
}

可以優化成:

:is(header, main, footer) p:hover {
color: red;
cursor: pointer;
}
提示

:is():where() 的作用相同,差別只在於它們的 specificity 不同。

:not()

:not() @ MDN

  • :not() 前面有空格和沒空格的意思不同
    • p:not(.foo) :找到元素是 <p>,但 class 不為 .foo 的元素
    • p :not(.foo)<p> 元素中,class 不為 .foo 的「所有」元素
  • :not(.foo, .bar) 的作用等同於 :not(.foo):not(.bar)
/* CREDIT: https://developer.mozilla.org/en-US/docs/Web/CSS/:not */

/* 除了 class 是 .fancy 的其他所有 <p> */
p:not(.fancy) {
color: green;
}

/* <body> 中除了 <p> 之外的所有元素 */
body :not(p) {
text-docoration: underline;
}

/* <body> 中除了 <div> 或 <span> 的所有元素 */
body :not(div):not(span) {
font-weight: bold;
}

/* 等同於上面的寫法 */
body :not(div, span) {
font-weight: bold;
}

也可以搭配其他 selector 做組合技:

/* article 中所有 h2, h4, h5,以及「所有不是在 aside 裡的 h3」 */
article :is(h2, h3:not(aside h3), h4, h5) {
/* rules */
}

:has():如果有...則

:has() @ MDN

透過 :has() 可以用來「檢驗某個條件是否符合」,如果符合的話才套用特定的 CSS:

/* CREDIT: https://developer.mozilla.org/en-US/docs/Web/CSS/:has */

/* 如果 a 裡直接有 img,則套用特定樣式到 a 上 */
a:has(> img) {
/* rules */
}

/* 如果 h1 後面直接跟著 p,則套用特定樣式在 h1 上面 */
h1:has(+ p) {
color: red;
}

/* 如果 ul 中 li 有第 6 個 child,則以兩欄的方式顯示 */
ul:has(li:nth-child(6)) {
columns: 2;
}

/* 如果 ul 中 li 有第 11 個 child,則以三欄的方式顯示 */
ul:has(li:nth-child(6)) {
columns: 3;
}

參考資料

Giscus