CSS 2022 現況

Google I/O 2022 介紹的網頁樣式功能,以及一些額外功能。

2022 年將是 CSS 發展最蓬勃的一年,不僅有許多新功能,瀏覽器也將推出合作功能,共同實作 14 項功能!

總覽

這篇文章是 2022 年 Google IO 大會演講的文字稿。這份指南並非要深入介紹各項功能,而是提供簡要的概覽,引起您的興趣,因此著重廣度而非深度。如想進一步瞭解,請參閱各節結尾的資源連結。

目錄

請使用下方清單跳至感興趣的主題:

瀏覽器相容性

許多 CSS 功能都設定為共同發布,主要原因在於 Interop 2022 的努力。在研究 Interop 計畫之前,請務必先瞭解 Compat 2021 的努力成果。

Compat 2021

2021 年的目標是根據開發人員透過問卷調查提供的意見回饋,穩定目前的功能、改善測試套件,並提高瀏覽器在五項功能中的通過分數:

  1. sticky定位
  2. aspect-ratio 尺寸
  3. flex」版面配置
  4. grid」版面配置
  5. transform 定位和動畫

各項測試分數全面提升,顯示穩定性和可靠性有所改善。在此向這些團隊致上誠摯的祝賀!

Interop 2022

今年,各瀏覽器齊聚一堂,討論他們打算開發的功能和優先事項,共同努力。他們計畫為開發人員提供下列網頁功能:

  1. @layer
  2. 色域和函式
  3. 防堵
  4. <dialog>
  5. 表單相容性
  6. 捲動
  7. 子格線
  8. 字體排版
  9. 可視區域單位
  10. 網頁相容性

這份名單令人期待且雄心勃勃,我等不及要看後續發展。

2022 年全新內容

不令人意外的是,Interop 2022 計畫對 2022 年的 CSS 狀態造成重大影響。

層疊圖層

Browser Support

  • Chrome: 99.
  • Edge: 99.
  • Firefox: 97.
  • Safari: 15.4.

Source

@layer 之前,載入的樣式表順序非常重要,因為最後載入的樣式可以覆寫先前載入的樣式。這導致開發人員必須先載入較不重要的樣式,再載入較重要的樣式,因此需要仔細管理進入樣式表。開發人員可運用整套方法來管理這項重要性,例如 ITCSS

使用 @layer 時,輸入檔案可以預先定義圖層及其順序。然後,在載入或定義樣式時,這些樣式可以放置在圖層中,保留樣式覆寫重要性,但不必仔細管理載入協調程序。

影片:顯示定義的層疊層如何讓編寫和載入程序更自由,同時視需要維持層疊。

Chrome 開發人員工具有助於顯示樣式來自哪些層:

螢幕截圖:Chrome 開發人員工具的「樣式」側欄,醒目顯示新圖層群組中的樣式。

資源

子格線

Browser Support

  • Chrome: 117.
  • Edge: 117.
  • Firefox: 71.
  • Safari: 16.

Source

subgrid 之前,另一個格線內的格線無法與父項儲存格或格線對齊。每個格線版面配置都不一樣。許多設計師會在整個設計上放置單一格線,並持續對齊其中的項目,但這無法在 CSS 中完成。

subgrid 之後,格線的子項可以採用父項的欄或列做為自己的欄或列,並將自己或子項對齊這些欄或列!

在下列示範中,body 元素會建立三欄的傳統格線:中間欄稱為 main,左右兩欄則命名其線條 fullbleed。然後,主體中的每個元素 (<nav><main>) 會透過設定 grid-template-columns: subgrid,採用主體中的具名線條。

​​body {
  display: grid;
  grid-template-columns:
    [fullbleed-start]
    auto [main-start] min(90%, 60ch) [main-end] auto
    [fullbleed-end]
  ;
}

body > * {
  display: grid;
  grid-template-columns: subgrid;
}

最後,<nav><main> 的子項可以使用 fullbleedmain 欄和線對齊或調整大小。

.main-content {
  grid-column: main;
}

.fullbleed {
  grid-column: fullbleed;
}

開發人員工具可協助您查看線條和子格線 (目前僅限 Firefox)。在下圖中,父項格線和子格線已重疊。現在的版面配置與設計師的構想相符。

子格線範例的螢幕截圖,使用 Chrome 開發人員工具格線疊加工具顯示 CSS 定義的線條。

在開發人員工具的元素面板中,您可以查看哪些元素是格線和子格線,這對偵錯或驗證版面配置非常有幫助。

Chrome 開發人員工具「元素」面板的螢幕截圖,標示出具有格線或子格線版面配置的元素。
Firefox 開發人員工具的螢幕截圖

資源

容器查詢

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 110.
  • Safari: 16.

Source

@container 之前,網頁元素只能回應整個可視區域的大小。這很適合巨集版面配置,但如果是微版面配置,且外部容器並非整個檢視區塊,版面配置就無法相應調整。

@container 之後,元素就能回應父項容器的大小或樣式!唯一要注意的是,容器必須宣告自己是可能的查詢目標,這項小小的要求能帶來很大的好處。

/* establish a container */
.day {
  container-type: inline-size;
  container-name: calendar-day;
}

這些樣式可讓事件元素查詢下列影片中的週一、週二、週三、週四和週五欄位。

示範Una Kravets 提供

以下是查詢 calendar-day 容器大小的 CSS,然後調整版面配置和字型大小:

@container calendar-day (max-width: 200px) {
  .date {
    display: block;
  }

  .date-num {
    font-size: 2.5rem;
    display: block;
  }
}

以下是另一個範例:一個書籍元件會根據拖曳至的欄位空間調整大小:

示範Max Böck 提供

Una 正確評估情況,認為這是新的回應式。使用 @container 時,您會做出許多令人興奮且有意義的設計決策。

資源

accent-color

Browser Support

  • Chrome: 93.
  • Edge: 93.
  • Firefox: 92.
  • Safari: 15.4.

Source

accent-color 推出前,如果想使用與品牌相符的顏色製作表單,您可能會使用複雜的程式庫或 CSS 解決方案,但這些解決方案隨著時間推移會變得難以管理。雖然他們提供了所有選項,也希望包含無障礙功能,但選擇使用內建元件或採用自己的元件,會變得難以持續選擇。

accent-color後,只要一行 CSS 程式碼,就能將品牌顏色帶入內建元件。除了色調,瀏覽器還會智慧地為元件的輔助部分選擇適當的對比色,並配合系統色彩配置 (淺色或深色)。

/* tint everything */
:root {
  accent-color: hotpink;
}

/* tint one element */
progress {
  accent-color: indigo;
}

並排顯示淺色和深色強調 HTML 元素,以供比較。

如要進一步瞭解 accent-color,請參閱 web.dev 上的文章,我將探討這個實用 CSS 屬性的更多面向。

資源

色彩等級 4 和 5

過去幾十年來,網頁一直以 sRGB 為主,但在高畫質螢幕和預先配備 OLED 或 QLED 螢幕的行動裝置不斷擴展的數位世界中,sRGB 已不敷使用。此外,使用者也期望網頁能根據個人偏好調整,因此色彩管理已成為設計師、設計系統和程式碼維護人員日益重視的問題。

不過,CSS 在 2022 年推出了多項新的顏色函式和空間: - 顏色可延伸至螢幕的 HD 顏色功能。 - 符合意圖的色域,例如感知均勻度。 - 漸層的色彩空間,會大幅改變插補結果。 - 顏色函式可協助您混合和對比顏色,並選擇要使用的空間。

在這些色彩功能推出前,設計系統需要預先計算適當的對比色,並確保調色盤的鮮豔度適中,而預先處理器或 JavaScript 則負責繁重的工作。

有了這些色彩功能,瀏覽器和 CSS 就能動態即時完成所有工作。不必傳送數 KB 的 CSS 和 JavaScript 給使用者,即可啟用主題和資料視覺化顏色,CSS 可負責協調及計算。CSS 也更適合在用量前檢查支援情形,或妥善處理備援。

@media (dynamic-range: high) {
  .neon-pink {
    --neon-glow: color(display-p3 1 0 1);
  }
}

@supports (color: lab(0% 0 0)) {
  .neon-pink {
    --neon-glow: lab(150% 160 0);
  }
}

hwb()

Browser Support

  • Chrome: 101.
  • Edge: 101.
  • Firefox: 96.
  • Safari: 15.

Source

HWB 代表色調、白度和黑度。這是一種方便人類表達顏色的方式,因為只要指定色調,以及要加入多少白色或黑色來調亮或調暗即可。如果藝術家會將顏色與白色或黑色混合,可能會很喜歡這項顏色語法新增功能。

使用這個顏色函式會產生 sRGB 色域的顏色,與 HSL 和 RGB 相同。就 2022 年的新功能而言,這項功能不會提供新顏色,但對於語法和心智模型的愛好者來說,這項功能可能會讓某些工作變得更輕鬆。

資源

色域

色彩空間會決定色彩的呈現方式。每個色彩空間都提供不同的功能,以及色彩處理的取捨。有些人可能會將所有鮮豔的顏色放在一起,有些人則可能會先根據亮度排列。

2022 年 CSS 將提供 10 個新色域,每個色域都有獨特功能,可協助設計師和開發人員顯示、挑選及混合顏色。以往只能使用 sRGB 處理顏色,但現在 CSS 解鎖了新的潛力,並提供新的預設色域 LCH。

color-mix()

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 16.2.

Source

color-mix()之前,開發人員和設計師需要使用 Sass 等前置處理器混合顏色,瀏覽器才能看到這些顏色。此外,大多數的混色函式也未提供選項,讓您指定要混色的色彩空間,有時會導致結果令人困惑。

color-mix() 之後,開發人員和設計師可以在瀏覽器中混合顏色,以及所有其他樣式,不必執行建構程序或加入 JavaScript。此外,他們可以指定要混合的色域,或使用 LCH 的預設混合色域。

通常會以品牌顏色做為基礎,並從中建立變體,例如用於懸停樣式的較淺或較深顏色。以下是使用 color-mix() 的範例:

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(var(--brand) 25%, black);
  --lighter: color-mix(var(--brand) 25%, white);
}

如要在其他色彩空間 (例如 srgb) 中混合這些顏色,請變更色彩空間:

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(in srgb, var(--brand) 25%, black);
  --lighter: color-mix(in srgb, var(--brand) 25%, white);
}

以下是使用 color-mix() 的主題設定示範。嘗試變更品牌顏色,並觀察主題更新情形:

2022 年,您可以在樣式表中使用各種色彩空間混合顏色!

資源

color-contrast()

color-contrast() 之前,樣式表作者必須預先瞭解無障礙顏色。調色盤通常會在色樣上顯示黑色或白色文字,向色彩系統使用者指出與該色樣適當對比所需的文字顏色。

螢幕截圖:3 個 Material 調色盤,顯示 14 種顏色和適合用於文字的白色或黑色對比色。
2014 年 Material Design 調色盤的範例

color-contrast()後,樣式表作者就能將這項工作完全交給瀏覽器。您不僅可以讓瀏覽器自動挑選黑色或白色,還能提供設計系統適用的顏色清單,讓瀏覽器挑選第一個通過所需對比度的顏色。

以下是 HWB 調色盤設定示範的螢幕截圖,其中文字顏色是由瀏覽器根據色樣顏色自動選擇:

HWB 示範的螢幕截圖,其中每個調色盤都有不同的淺色或深色文字配對,由瀏覽器決定。
試用示範版

語法基本如下所示,其中灰色會傳遞至函式,而瀏覽器會判斷黑色或白色是否具有最大對比度:

color: color-contrast(gray);

您也可以使用顏色清單自訂函式,函式會從選取範圍中挑選對比度最高的顏色:

color: color-contrast(gray vs indigo, rebeccapurple, hotpink);

最後,如果不想從清單中選取對比度最高的顏色,可以提供目標對比度,系統會選擇第一個通過該對比度的顏色:

color: color-contrast(
  var(--bg-blue-1)
  vs
  var(--text-lightest), var(--text-light), var(--text-subdued)
  to AA /* 4.5 could also be passed */
);

這個函式不只可用於文字顏色,但估計主要用途是文字顏色。試想一下,一旦 CSS 語言本身內建適當的對比色選擇功能,提供無障礙且清晰易讀的介面將會變得多麼容易。

資源

相對顏色語法

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 113.
  • Safari: 15.

Source

在相對顏色語法推出前,如要計算顏色並進行調整,必須將顏色通道個別放入自訂屬性。這項限制也讓 HSL 成為操控色彩的主要顏色函式,因為色調、飽和度或亮度都可以透過 calc() 輕鬆調整。

在相對顏色語法之後,任何空間中的任何顏色都可以解構、修改,並以顏色形式傳回,所有動作都可以在一行 CSS 中完成。不再受限於 HSL,可在任何所需色彩空間中進行操控,且只需建立較少的自訂屬性即可。

在下列語法範例中,系統會提供基本十六進位值,並根據該值建立兩種新顏色。第一個顏色 --absolute-change 會從基本顏色在 LCH 中建立新顏色,然後將基本顏色的亮度替換為 75%,同時維持色度 (c) 和色相 (h)。第二個顏色 --relative-change 會從基本顏色在 LCH 中建立新顏色,但這次會將色度 (c) 減少 20%。

.relative-color-syntax {
  --color: #0af;
  --absolute-change: lch(from var(--color) 75% c h);
  --relative-change: lch(from var(--color) l calc(c-20%) h);
}

這類似於混色,但更像是變更,而非混合。您可以從其他顏色轉換顏色,並存取所用顏色函式命名的三個管道值,還可調整這些管道。總而言之,這是非常酷炫且強大的顏色語法。

在下列範例中,我使用相對顏色語法建立基本色的淺色和深色變體,並使用 color-contrast() 確保標籤具有適當的對比度:

螢幕截圖,有 3 個資料欄,每個資料欄都比中間的資料欄深或淺。
試用示範版

這項函式也可用於生成調色盤。以下是示範,其中整個調色盤都是根據提供的基底顏色產生。這組 CSS 可支援所有調色盤,每個調色盤只是提供不同的基底。此外,由於我使用了 LCH,請看看調色盤在感知上有多麼均勻,完全沒有熱點或死點,這都要歸功於這個色域。

:root {
  --_color-base: #339af0;

  --color-0:  lch(from var(--_color-base) 98% 10 h);
  --color-1:  lch(from var(--_color-base) 93% 20 h);
  --color-2:  lch(from var(--_color-base) 85% 40 h);
  --color-3:  lch(from var(--_color-base) 75% 46 h);
  --color-4:  lch(from var(--_color-base) 66% 51 h);
  --color-5:  lch(from var(--_color-base) 61% 52 h);
  --color-6:  lch(from var(--_color-base) 55% 57 h);
  --color-7:  lch(from var(--_color-base) 49% 58 h);
  --color-8:  lch(from var(--_color-base) 43% 55 h);
  --color-9:  lch(from var(--_color-base) 39% 52 h);
  --color-10: lch(from var(--_color-base) 32% 48 h);
  --color-11: lch(from var(--_color-base) 25% 45 h);
  --color-12: lch(from var(--_color-base) 17% 40 h);
  --color-13: lch(from var(--_color-base) 10% 30 h);
  --color-14: lch(from var(--_color-base) 5% 20 h);
  --color-15: lch(from var(--_color-base) 1% 5 h);
}
螢幕截圖:15 個調色盤,全都是由 CSS 動態產生。
試用示範版

希望您現在已瞭解如何根據色彩空間和不同色彩函式的優缺點,將這些工具用於不同用途。

資源

漸層色彩空間

在漸層色域推出前,系統預設使用 sRGB 色域。sRGB 一般來說很可靠,但也有一些缺點,例如灰色死區

格狀檢視畫面中的 4 個漸層,皆為青色到深粉紅色。LCH 和 LAB 的鮮豔度較為一致,而 sRGB 在中間會稍微不飽和。

在漸層色域之後,請告知瀏覽器要使用哪個色域進行顏色插補。開發人員和設計師可以選擇偏好的漸層。預設色域也會變更為 LCH,而非 sRGB。

新增的語法會放在漸層方向之後,使用新的 in 語法,而且是選用項目:

background-image: linear-gradient(
  to right in hsl,
  black, white
);

background-image: linear-gradient(
  to right in lch,
  black, white
);

以下是從黑色到白色的基本漸層。查看各個色域的結果範圍。有些會比其他顏色更早達到深黑色,有些則太晚褪色為白色。

顯示 11 個比較黑色和白色的色彩空間。

在下一個範例中,黑色會轉換為藍色,因為這是漸層的已知問題。在色彩插補期間,大多數的色域都會逐漸變成紫色,或者如我所想,色彩在色域內從 A 點移動到 B 點時,也會逐漸變成紫色。由於漸層會從 A 點到 B 點呈現直線,因此色域的形狀會大幅改變路徑沿途的停靠點。

顯示 11 個色域,比較藍色和黑色。

如需深入探討、查看範例和留言,請參閱這則 Twitter 討論串

資源

inert

Browser Support

  • Chrome: 102.
  • Edge: 102.
  • Firefox: 112.
  • Safari: 15.5.

Source

inert 之前,引導使用者將焦點放在需要立即注意的網頁或應用程式區域,是良好的做法。這種導覽焦點策略稱為「焦點陷阱」,因為開發人員會將焦點放在互動空間中,監聽焦點變更事件,如果焦點離開互動空間,就會強制返回。使用鍵盤或螢幕閱讀器的使用者會返回互動空間,確保完成工作後再繼續。

inert 之後,您不需要進行任何陷阱作業,因為可以凍結或保護網頁或應用程式的整個區段。當文件中的這些部分處於閒置狀態時,點擊和焦點變更嘗試就無法使用。也可以將此功能視為警衛,而非陷阱。inert 並非要您待在某個地方,而是要讓您無法前往其他地方。

JavaScript alert() 函式就是一個很好的例子:

網站顯示為互動式,然後呼叫 alert(),網頁不再處於活動狀態。

請注意,在呼叫 alert() 之前,上述影片中的網頁可透過滑鼠和鍵盤存取。警示對話方塊彈出後,頁面其餘部分凍結或 inert。使用者的焦點會放在快訊對話方塊內,無法前往其他位置。使用者互動並完成快訊函式要求後,網頁就會再次進入互動狀態。inert,讓開發人員輕鬆達成相同的引導式焦點體驗。

以下是說明運作方式的小程式碼範例:

<body>
  <div class="modal">
    <h2>Modal Title</h2>
    <p>...<p>
    <button>Save</button>
    <button>Discard</button>
  </div>
  <main inert>
    <!-- cannot be keyboard focused or clicked -->
  </main>
</body>

對話方塊就是一個很好的例子,但 inert 也適用於側邊滑出式選單等使用者體驗。使用者滑出側邊選單時,不應允許滑鼠或鍵盤與後方網頁互動,這會讓使用者感到困惑。當側邊選單顯示時,請讓頁面處於閒置狀態,使用者必須關閉或瀏覽該側邊選單,不會在選單開啟時迷失在頁面其他位置。

資源

COLRv1 字型

在 COLRv1 字型推出前,網路上有 OT-SVG 字型,這也是一種開放格式,可製作內建漸層、顏色和效果的字型。不過,這些貼紙可能會變得非常大,而且雖然可以編輯文字,但自訂空間不大。

COLRv1 字型之後,網頁現在可使用體積更小、可縮放向量、可重新定位、具備漸層效果,以及支援混合模式的字型,並接受參數來根據用途自訂字型,或配合品牌風格。

比較視覺化和長條圖,顯示 COLRv1 字型更銳利且更小。
圖片來源:https://developer.chrome.com/blog/colrv1-fonts/

以下是 Chrome 開發人員網誌中關於表情符號的文章範例。您可能已經發現,如果放大表情符號的字型大小,表情符號不會保持清晰。這是圖片,而非向量藝術。在應用程式中,如果使用表情符號,通常會換成更高品質的素材資源。使用 COLRv1 字型時,表情符號會以向量形式呈現,而且非常美觀:

圖示字型可透過這個格式呈現許多精彩內容,例如自訂雙色調色盤等。載入 COLRv1 字型的方式與其他字型檔案相同:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

如要自訂 COLRv1 字型,請使用 @font-palette-values,這是特殊的 CSS at 規則,可將一組自訂選項分組並命名為套件,以供日後參照。請注意,您指定自訂名稱的方式與自訂屬性相同,都是以 -- 開頭:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

--colorized 做為自訂項目的別名,最後一個步驟是將調色盤套用至使用顏色字型系列的元素:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

.spicy {
  font-family: "Bungee Spice";
  font-palette: --colorized;
}
螢幕截圖:Bungee Spice 字型,顯示「DUNE」一詞。
Bungee Spice 字型,搭配自訂顏色,來源:https://developer.chrome.com/blog/colrv1-fonts/

隨著越來越多可變字型和彩色字型推出,網頁排版正朝著豐富的自訂功能和創意表現邁進。

資源

可視區域單位

圖片:裝置螢幕、瀏覽器視窗和 iframe 的檢視區塊各不相同。

在推出新的可視區域變體前,網頁提供實體單位,協助調整可視區域。分別是高度、寬度、最小尺寸 (vmin) 和最大邊 (vmax)。這些做法在許多方面都相當實用,但行動瀏覽器卻帶來了複雜性。

在行動裝置上載入網頁時,系統會顯示含有網址的狀態列,而這個狀態列會佔用部分可視區域空間。幾秒後,狀態列可能會滑開,讓使用者享有更大的檢視區塊體驗。但當該列滑出時,可視區域高度會變更,任何 vh 單元都會隨著目標大小變更而位移和調整大小。在後來的幾年,vh 單位需要特別決定要使用哪一種可視區域大小,因為這會在行動裝置上造成視覺版面配置問題。我們判斷 vh 一律代表最大的可視區域。

.original-viewport-units {
  height: 100vh;
  width: 100vw;
  --size: 100vmin;
  --size: 100vmax;
}

推出新的可視區域變體後,系統會提供小型、大型和動態可視區域單元,並新增與實體單元對應的邏輯單元。我們的想法是讓開發人員和設計師能夠根據特定情境,選擇要使用的單位。狀態列消失時,或許可以接受版面配置發生小幅度的突兀變化,這樣就能放心使用 dvh (動態可視區高度)。

圖片中顯示三部手機,說明 DVH、LVH 和 SVH。DVH
   範例手機有兩條垂直線,一條位於搜尋列底部和檢視區塊底部之間,另一條位於搜尋列上方 (系統狀態列下方) 和檢視區塊底部之間,顯示 DVH 可以是這兩種長度。LVH 顯示在中間,裝置狀態列底部和手機檢視區塊按鈕之間有一條線。最後一個是 SVH 單位範例,顯示從瀏覽器搜尋列底部到檢視區塊底部的線條

以下完整列出新視埠變數提供的所有新視埠單位選項:

高度可視區域單位
​​.new-height-viewport-units {
  height: 100vh;
  height: 100dvh;
  height: 100svh;
  height: 100lvh;
  block-size: 100vb;
  block-size: 100dvb;
  block-size: 100svb;
  block-size: 100lvb;
}
可視區域寬度單位
.new-width-viewport-units {
  width: 100vw;
  width: 100dvw;
  width: 100svw;
  width: 100lvw;
  inline-size: 100vi;
  inline-size: 100dvi;
  inline-size: 100svi;
  inline-size: 100lvi;
}
最小可視區域側邊單位
.new-min-viewport-units {
  --size: 100vmin;
  --size: 100dvmin;
  --size: 100svmin;
  --size: 100lvmin;
}
最大的可視區域側邊單元
.new-max-viewport-units {
  --size: 100vmax;
  --size: 100dvmax;
  --size: 100svmax;
  --size: 100lvmax;
}

希望這些功能可以為開發人員和設計師提供所需的彈性,實現視埠回應式設計。

資源

:has()

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Source

:has() 之前,選取器主體一律位於結尾。舉例來說,這個選取器的主體是清單項目:ul > li。虛擬選取器可以變更選取器,但不會變更主體:ul > li:hoverul > li:not(.selected)

:has() 之後,元素樹狀結構中較高的主體可以繼續做為主體,同時提供有關子項的查詢:ul:has(> li)。很容易就能瞭解 :has() 為何會得到「父項選取器」這個通用名稱,因為選取器的主體現在是這個案例中的父項。

以下是基本語法範例,其中類別 .parent 仍為主體,但只有在子元素具有 .child 類別時才會選取:

.parent:has(.child) {...}

以下範例中,<section> 元素是主體,但只有在其中一個子項含有 :focus-visible 時,選取器才會相符:

section:has(*:focus-visible) {...}

一旦實用用途顯而易見,:has() 選取器就會再次成為絕佳的實用工具。舉例來說,目前無法選取包裝圖片的 <a> 標記,因此很難教導錨點標記在該用途中如何變更樣式。不過,您可以使用 :has() 執行這項操作:

a:has(> img) {...}

以上範例中,:has() 看起來都只是父項選取器。 請考慮在 <figure> 元素中使用圖片的應用情境,並在圖案有 <figcaption> 時調整圖片樣式。在下列範例中,系統會選取附有圖說文字的圖,然後選取該情境中的圖片。:has() 用於圖片,不會變更主體,因為我們鎖定的主體是圖片而非圖:

figure:has(figcaption) img {...}

組合方式似乎無窮無盡。將 :has()數量查詢結合,並根據子項數量調整 CSS 格線版面配置。結合 :has()互動式虛擬類別狀態,以全新的創意方式建立回應式應用程式。

使用 @supportsselector() 函式,即可輕鬆檢查是否支援,這項函式會先測試瀏覽器是否瞭解語法,再使用語法:

@supports (selector(:has(works))) {
  /* safe to use :has() */
}

資源

2022 年及後續

2022 年推出這些強大功能後,仍有許多事情難以做到。下一節將探討一些尚未解決的問題,以及目前積極開發的解決方案。即使這些解決方案可能在瀏覽器中指定或透過旗標提供,仍處於實驗階段。

接下來各節的重點在於讓您放心,許多公司都有許多人正在尋求解決這些問題,而不是這些解決方案將在 2023 年發布。

寬鬆型別的自訂屬性

Browser Support

  • Chrome: 85.
  • Edge: 85.
  • Firefox: 128.
  • Safari: 16.4.

Source

CSS 自訂屬性非常實用,這類變數可儲存各種資料,並進行擴充、計算、共用等操作。事實上,這些函式過於彈性,如果能有一些彈性較小的函式,會是更好的選擇。

假設 box-shadow 使用自訂屬性做為值:

box-shadow: var(--x) var(--y) var(--blur) var(--spread) var(--color);

一切運作正常,直到其中一個屬性變更為 CSS 不接受的值 (例如 --x: red) 為止。如果任何巢狀變數遺漏或設為無效值類型,整個陰影就會中斷。

這時 @property 就派上用場了:--x 可以成為型別自訂屬性,不再寬鬆彈性,而是具有定義界線的安全屬性:

@property --x {
  syntax: '<length>';
  initial-value: 0px;
  inherits: false;
}

現在,當 box-shadow 使用 var(--x),稍後嘗試 --x: red 時,系統會忽略 red,因為它不是 <length>。也就是說,即使其中一個自訂屬性收到無效值,陰影仍會繼續運作。不會失敗,而是會回復為 0pxinitial-value

動畫

除了型別安全之外,這也為動畫開啟了許多可能性。CSS 語法彈性十足,但有些項目無法製作動畫,例如漸層。@property 可在此提供協助,因為輸入的 CSS 屬性可讓瀏覽器瞭解開發人員在過於複雜的插補中的意圖。這項功能可大幅縮小可能性範圍,讓瀏覽器能為先前無法製作動畫的樣式屬性製作動畫。

請參考這個示範範例,其中使用放射狀漸層製作疊加層的一部分,營造聚光燈效果。JavaScript 會在按下 Alt/Opt 鍵時設定滑鼠的 x 和 y 座標,然後將焦點大小變更為較小的值 (例如 25%),在滑鼠位置建立聚光燈焦點圓圈:

試用示範版
.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );
}

不過,漸層無法製作成動畫。這些動畫過於彈性且複雜,瀏覽器「無法直接推導」出您想要的動畫效果。不過,使用 @property 時,可以單獨輸入及製作某項屬性的動畫,瀏覽器可以輕鬆瞭解意圖。

使用此對焦效果的電玩遊戲一律會將圓圈從大圓圈動畫化為針孔圓圈。以下說明如何在我們的示範中搭配使用 @property,讓瀏覽器為漸層遮罩製作動畫:

@property --focal-size {
  syntax: '<length-percentage>';
  initial-value: 100%;
  inherits: false;
}

.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );

  transition: --focal-size .3s ease;
}
試用示範版

現在,瀏覽器可以為漸層大小加上動畫效果,因為我們已將修改的表面積縮減至只有一個屬性,並輸入值,因此瀏覽器可以智慧地插補長度。

@property 的功能遠不止於此,但這些小小的啟用動作就能帶來大大的成效。

資源

曾造訪min-widthmax-width

在媒體查詢範圍之前,CSS 媒體查詢會使用 min-widthmax-width 來表達大於和低於條件。畫面可能會如下所示:

@media (min-width: 320px) {
  
}

媒體查詢範圍之後,相同的媒體查詢可能如下所示:

@media (width >= 320px) {
  
}

同時使用 min-widthmax-width 的 CSS 媒體查詢可能如下所示:

@media (min-width: 320px) and (max-width: 1280px) {
  
}

媒體查詢範圍之後,相同的媒體查詢可能如下所示:

@media (320px <= width <= 1280px) {
  
}

視您的程式碼背景而定,其中一個會比另一個更易於閱讀。有了這些規格,開發人員就能選擇偏好的規格,甚至交替使用。

資源

沒有媒體查詢變數

@custom-media 之前,媒體查詢必須不斷重複,或依賴前置處理器在建構期間根據靜態變數產生適當的輸出內容。

@custom-media 之後,CSS 允許別名媒體查詢並參照這些查詢,就像自訂屬性一樣。

命名非常重要:可讓用途與語法保持一致,方便團隊分享及使用。以下是幾個自訂媒體查詢,可讓我在專案之間切換時繼續使用:

@custom-media --OSdark  (prefers-color-scheme: dark);
@custom-media --OSlight (prefers-color-scheme: light);

@custom-media --pointer (hover) and (pointer: coarse);
@custom-media --mouse   (hover) and (pointer: fine);

@custom-media --xxs-and-above (width >= 240px);
@custom-media --xxs-and-below (width <= 240px);

定義完成後,我就可以使用其中一個,如下所示:

@media (--OSdark) {
  :root {
    
  }
}

如要查看我在 CSS 自訂屬性程式庫 Open Props 中使用的完整自訂媒體查詢清單,請點選連結。

資源

巢狀選取器非常實用

@nest 之前,樣式表中有許多重複內容。當選取器很長,且每個選取器都針對細微差異時,這種做法就特別難以管理。巢狀結構的便利性是採用前置處理器最常見的原因之一。

@nest後,重複週期就會消失。CSS 內建的巢狀結構功能,幾乎與預先處理器支援的巢狀結構功能相同。

article {
  color: darkgray;
}

article > a {
  color: var(--link-color);
}

/* with @nest becomes */

article {
  color: darkgray;

  & > a {
    color: var(--link-color);
  }
}

對我來說,除了不會在巢狀選取器中重複 article 之外,巢狀結構最重要的優點就是樣式環境會保留在一個樣式區塊中。讀者不必從一個選取器及其樣式,跳到另一個具有樣式的選取器 (範例 1),而是可以留在文章的脈絡中,查看文章擁有的連結。關係和樣式意圖會綁在一起,因此 article 會顯示為擁有自己的樣式。

擁有權也可以視為集中化。不必在樣式表尋找相關樣式,所有樣式都會巢狀內嵌在環境中。這項功能適用於父項與子項關係,也適用於子項與父項關係。

假設子項元件想在不同的父項情境中自行調整,而不是由父項擁有樣式並變更子項:

/* parent owns this, adjusting children */
section:focus-within > article {
  border: 1px solid hotpink;
}

/* with @nest becomes */

/* article owns this, adjusting itself when inside a section:focus-within */
article {
  @nest section:focus-within > & {
     border: 1px solid hotpink;
  }
}

@nest 有助於整體改善樣式組織、集中管理和擁有權,元件可以將自己的樣式分組並擁有這些樣式,而不是將樣式分散到其他樣式區塊中。在這些範例中,這項變更可能看似微不足道,但無論是便利性還是可讀性,都可能受到極大影響。

資源

範圍樣式非常難

Browser Support

  • Chrome: 118.
  • Edge: 118.
  • Firefox: behind a flag.
  • Safari: 17.4.

Source

@scope 之前,由於 CSS 中的樣式會層疊、繼承,且預設為全域範圍,因此存在許多策略。CSS 的這些功能在許多方面都非常方便,但對於複雜的網站和應用程式 (可能包含許多不同樣式的元件) 而言,全域空間和層疊的性質可能會導致樣式感覺像是外洩。

@scope 之後,樣式不僅可以限定在特定環境 (例如類別) 內,也可以明確指出樣式的結束位置,不會繼續疊加或繼承。

在以下範例中,BEM 命名慣例範圍可以反向轉換為實際意圖。BEM 選取器會嘗試將 header 元素的顏色範圍限定為具有命名慣例的 .card 容器。這項要求表示標頭必須含有這個類別名稱,才能完成目標。使用 @scope 時,您不必遵守任何命名慣例,即可完成相同目標,且不必標記標頭元素:

.card__header {
  color: var(--text);
}

/* with @scope becomes */

@scope (.card) {
  header {
    color: var(--text);
  }
}

以下是另一個範例,這個範例較不著重於特定元件,而是著重於 CSS 的全域範圍性質。深色和淺色主題必須共存於單一樣式表,而決定勝出樣式的順序非常重要。通常這表示深色主題樣式會出現在淺色主題之後;這會將淺色設為預設樣式,深色設為選用樣式。避免與 @scope 發生排序和範圍衝突:

​​@scope (.light-theme) {
  a { color: purple; }
}

@scope (.dark-theme) {
  a { color: plum; }
}

為完整說明,@scope也允許建立樣式範圍的結束位置。這無法透過任何命名慣例或前置處理器完成,只有瀏覽器內建的 CSS 才能做到。在下列範例中,只有當 .media-block 的子項是 .content 的同層或父項時,才會套用 img.content 樣式:

@scope (.media-block) to (.content) {
  img {
    border-radius: 50%;
  }

  .content {
    padding: 1em;
  }
}

資源

CSS 無法用於格狀版面配置

在 CSS 砌磚格線出現之前,JavaScript 是實現砌磚版面配置的最佳方式,因為任何使用欄或 Flexbox 的 CSS 方法都會不準確地呈現內容順序。

使用 CSS 格狀磚後,就不需要 JavaScript 程式庫,內容順序也會正確。

顯示數字沿著頂端移動,然後向下移動的方格布局螢幕截圖。
Smashing Magazine 的圖片和示範
https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/

上述範例是透過下列 CSS 達成:

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

令人欣慰的是,這項缺少的版面配置策略已列入開發計畫,而且您今天就能在 Firefox 中試用

資源

CSS 無法協助使用者減少資料用量

Browser Support

  • Chrome: behind a flag.
  • Edge: behind a flag.
  • Firefox: not supported.
  • Safari: not supported.

Source

prefers-reduced-data 媒體查詢之前,JavaScript 和伺服器可以根據使用者的作業系統或瀏覽器的「節省數據用量」選項變更行為,但 CSS 無法。

prefers-reduced-data 媒體查詢之後,CSS 就能加入使用者體驗強化作業,並在節省資料方面發揮作用。

@media (prefers-reduced-data: reduce) {
  picture, video {
    display: none;
  }
}

上述 CSS 用於這個媒體捲動元件,可大幅節省費用。視造訪可視區域的大小而定,網頁載入時可節省的費用越多。使用者與媒體捲軸互動時,系統會繼續儲存。圖片都有 loading="lazy" 屬性,加上 CSS 會完全隱藏元素,因此系統不會發出圖片的網路請求。

電視節目輪播介面螢幕截圖,顯示許多縮圖和標題。

以我的測試為例,在可視區域中等大小的情況下,系統一開始載入 40 個要求和 700 KB 的資源。使用者捲動媒體選取畫面時,系統會載入更多要求和資源。使用 CSS 和縮減資料媒體查詢後,系統會載入 10 項要求和 172 KB 的資源。這樣可節省 0.5 MB 的資料,而且使用者甚至還沒捲動任何媒體,此時不會發出額外要求。

電視節目輪播介面的螢幕截圖,沒有縮圖,但顯示許多節目名稱。

除了節省數據用量,這項精簡數據功能還有更多優點。可查看更多標題,且不會有封面圖片分散注意力。許多使用者會以節省數據模式瀏覽,因為他們是依據每 MB 的數據量付費,因此看到 CSS 能在這方面提供協助,實在令人欣慰。

資源

捲動快照功能太少

在這些捲動快照提案推出前,如果自行編寫 JavaScript 來管理輪轉介面、滑桿或圖片庫,可能會因為所有觀察器和狀態管理而快速變得複雜。此外,如果不小心,指令碼可能會將自然捲動速度標準化,導致使用者互動感覺有點不自然,甚至可能不順暢。

全新的 API

snapChanging()

瀏覽器釋出子項目的瞬間,就會觸發這個事件。這樣一來,UI 就能反映缺少快速子項,以及捲軸的不確定快速狀態,因為捲軸現在正在使用中,且會停留在新的位置。

document.querySelector('.snap-carousel').addEventListener('snapchanging', event => {
  console.log('Snap is changing', event.snappedTargetsList);
});
snapChanged()

瀏覽器切換至新子項並停止捲動後,就會觸發這個事件。這可讓任何依附於已貼齊子項的 UI 更新並反映連線。

document.querySelector('.snap-carousel').addEventListener('snapchanged', event => {
  console.log('Snap changed', event.snappedTargetsList);
});
scroll-start

捲動不一定會從開頭開始。請考慮使用可滑動的元件,向左或向右滑動會觸發不同事件;或是載入網頁時,搜尋列一開始會隱藏,直到您捲動至頂端才會顯示。開發人員可使用這項 CSS 屬性,指定捲動器應從特定點開始。

:root { --nav-height: 100px }

.snap-scroll-y {
  scroll-start-y: var(--nav-height);
}
:snap-target

這個 CSS 選取器會比對捲動快照容器中的元素,這些元素目前由瀏覽器快照。

.card {
  --shadow-distance: 5px;
  box-shadow: 0 var(--shadow-distance) 5px hsl(0 0% 0% / 25%);
  transition: box-shadow 350ms ease;
}

.card:snapped {
  --shadow-distance: 30px;
}

有了這些捲動快照提案,製作滑桿、輪播或圖片庫就容易多了,因為瀏覽器現在提供這項工作的便利性,可使用內建 API,不必再使用觀察器和捲動協調程式碼。

這些 CSS 和 JS 功能仍處於早期階段,但請密切注意,我們很快就會推出有助於採用及測試這些功能的 Polyfill。

資源

在已知狀態之間循環切換

toggle() 之前,只能使用瀏覽器內建的狀態來設定樣式和互動。舉例來說,核取方塊輸入內容具有 :checked,這是輸入內容的內部管理瀏覽器狀態,CSS 可用於變更元素的外觀。

toggle() 之後,您可以在任何元素上建立自訂狀態,供 CSS 變更及用於設定樣式。可進行分組、循環、定向切換等操作。

在下列範例中,清單項目完成時會加上刪除線,但沒有任何核取方塊元素:

<ul class='ingredients'>
   <li>1 banana
   <li>1 cup blueberries
  ...
</ul>

以及相關的 CSS toggle() 樣式:

li {
  toggle-root: check self;
}

li:toggle(check) {
  text-decoration: line-through;
}

如果您熟悉狀態機,可能會發現這與 toggle() 有許多相似之處。這項功能可讓開發人員在 CSS 中建構更多狀態,希望藉此以更清楚且語意化的方式協調互動和狀態。

資源

自訂選取元素

<selectmenu> 之前,CSS 無法自訂含有豐富 HTML 的 <option> 元素,也無法大幅變更選項清單的顯示方式。因此開發人員必須載入外部程式庫,重新建立 <select> 的大部分功能,這項作業相當耗時。

<selectmenu> 後,開發人員可以為選項元素提供豐富的 HTML,並視需要設定樣式,同時仍符合無障礙規定並提供語意 HTML。

在以下範例中 (取自 <selectmenu> 說明頁面),系統會建立含有基本選項的新選單:

<selectmenu>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</selectmenu>

CSS 可以指定元素的部分並設定樣式:

.my-select-menu::part(button) {
  color: white;
  background-color: red;
  padding: 5px;
  border-radius: 5px;
}

.my-select-menu::part(listbox) {
  padding: 10px;
  margin-top: 5px;
  border: 1px solid red;
  border-radius: 5px;
}

以紅色為輔色,外觀精緻的選單。

啟用網頁實驗標記後,即可在 Canary 版 Chromium 中試用 <selectmenu> 元素。2023 年起,請留意可自訂的選單元素。

資源

將元素錨定至其他元素

anchor() 之前,絕對和相對位置是提供給開發人員的位置策略,可讓子項元素在上層元素內移動。

anchor() 之後,開發人員可以將元素放置在其他元素上,無論這些元素是否為子項。開發人員也可以指定要以哪個邊緣為準來定位,以及其他用於在元素之間建立位置關係的細節。

如要進一步瞭解,說明文章中提供了一些絕佳範例和程式碼範例。

資源