大家好,我是若川。持續組織了8個月源碼共讀活動,感興趣的可以?點此加我微信ruochuan12?參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》?包含20余篇源碼文章。歷史面試系列。另外:目前建有江西|湖南|湖北
籍前端群,可加我微信進群。
2022年將成為 CSS 最偉大的一年。無論是在功能還是合作瀏覽器的功能發布方面,合作目標是實現 14 個功能。
概述
本文是在 Google IO 2022上發表的演講的文字形式。這里不會對每個功能進行深入的講解,而是對每個功能進行簡要概述,提供廣度而不是深度。
下面是這些 CSS 功能的概覽:

瀏覽器兼容性
將這么多 CSS 功能設置為合作發布的主要原因是來自 Interop 2022 的努力,下面就來看看 Interop 2022 和 Compat 2021 分別做出了哪些努力。
1. Compat 2021
2021 年的目標是由開發人員通過調查獲得的反饋來推動的,旨在穩定當前功能、改進測試套件并提高瀏覽器在五個功能方面的通過分數:
sticky 定位
aspect-ratio 尺寸
flex 布局
grid 布局
transform 定位和動畫
測試分數全面提高,顯示出更高的穩定性和可靠性。
2. Interop 2022
今年,瀏覽器們齊心協力,討論了他們打算開發的功能和優先事項。他們計劃為開發者提供以下 web 功能:
級聯層
@layer
顏色空間和方法
容器查詢
<dialog>
表單兼容性
滾動
子網格
subgrid
排版
視口單位
Web 兼容
2022年的新功能
毫不疑問,CSS 2022 的狀態受到 Interop 2022 工作的巨大影響。
1. 級聯層(@layer)
瀏覽器支持:

在 @layer
之前,加載樣式表的順序非常重要,因為最后加載的樣式會覆蓋之前加載的樣式。這樣開發人員就需要先加載不太重要的樣式,然后再加載更重要的樣式。
在@layer
之后,入口文件可以預先定義圖層及其順序。然后,當樣式加載、加載完成或已經定義時,它們可以放置在一個層中,允許保留樣式覆蓋的重要性,但無需精心管理加載順序。

上圖展示了級聯層如何允許更自由、更開放地編寫和加載過程。同時仍然根據需要維護層疊。
Chrome DevTools 有助于可視化哪些樣式來自哪些圖層:

相關資源:
CSS Cascade 5 specification: https://www.w3.org/TR/css-cascade-5/#layering
Cascade layers explainer: https://css.oddbird.net/layers/explainer/
Cascade layers on MDN: https://developer.mozilla.org/docs/Web/CSS/@layer
Cascade Layers: https://developer.chrome.com/blog/cascade-layers/
Hello, CSS Cascade Layers: https://www.bram.us/2022/02/13/hello-css-cascade-layers/
2. 子網格(subgrid)
瀏覽器支持:

在subgrid
之前,另一個網格中的網格無法與其父單元格或網格線對齊。每個網格布局都是獨一無二的。許多設計師在他們的整個設計上放置一個網格,并不斷地在其中對齊項目,這在CSS中是做不到的。
在subgrid
之后,網格的子網格可以將其父網格的列或行作為自己的列或行,并將其自身或子網格與它們對齊!
在下面的demo中,body
元素創建了一個經典的三列網格,中間列為main
,左邊和右邊的列稱為fullbleed
。然后,body
中的每個元素, <nav>
和 <main>
通過設置 grid-template-columns: subgrid
來采用 body
中的命名行。
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>
的子級可以使用 fullbleed
和main
列和行對齊或調整自己的大小。
.main-content?{grid-column:?main;
}.fullbleed?{grid-column:?fullbleed;
}
完整示例:https://codepen.io/web-dot-dev/pen/JjMQzVV
目前,Firefox Devtools 可以幫助我們查看子網格。在下圖中,父網格和子網格已重疊。它現在類似于設計師對布局的思考方式。

在 Devtools 的“Elements”面板中,可以看到哪些元素是grid
和subgrid
,這對調試或驗證布局是非常有用的。

相關資源:
Spec: https://www.w3.org/TR/css-grid-2/#subgrids
MDN: https://developer.mozilla.org/docs/Web/CSS/CSS_Grid_Layout/Subgrid
Practical CSS Subgrid Video Tutorials: https://www.bram.us/2021/11/04/practical-css-subgrid-video-tutorials/
3. 容器查詢
在 @container
之前,網頁的元素只能響應整個視口的大小。這對于大型布局非常有用,但對于外部容器不是整個視口的小型布局,布局不可能進行相應調整。
在@container
之后,元素可以響應父容器的大小或樣式!唯一需要注意的是,容器必須將自己聲明為可能的查詢目標,這是一個很小的要求,可以帶來很大的好處。
/*?新建一個容器?*/
.day?{container-type:?inline-size;container-name:?calendar-day;
}
這些樣式使下圖中的 Mon、Tues、Wed、Thurs 和 Fri 列能夠被事件元素查詢。

以下CSS用于查詢 calendar-day
容器大小,然后調整布局和字體大小:
@container?calendar-day?(max-width:?200px)?{.date?{display:?block;}.date-num?{font-size:?2.5rem;display:?block;}
}
下面是另一個示例:一個book組件根據其拖動到的列中的可用空間進行調整:

相關資源:
Spec: https:/www.w3.org/TR/css-contain-3/#container-queries
Explainer: https://css.oddbird.net/rwd/query/explainer/
MDN: https://developer.mozilla.org/docs/Web/CSS/CSS_Container_Queries
The new responsive: https://web.dev/new-responsive/#responsive-to-the-container
Calendar demo by Una: https://codepen.io/una/pen/RwodQZw
**Awesome container queries: ** https://github.com/sturobson/Awesome-Container-Queries
Designcember: https://web.dev/how-we-built-designcember/
Container Queries are Actually Coming / Say Hello To CSS Container Queries: https://www.bram.us/2021/04/14/container-queries-are-actually-coming-say-hello-to-css-container-queries/
4. accent-color
瀏覽器支持:

在accent-color
之前,當我們想要一個與品牌顏色匹配的表單時,最終可能需要復雜的庫或CSS解決方案,隨著時間的推移,這些解決方案會變得難以管理。雖然它們提供了所有選項,并希望包括可訪問性,但選擇使用內置組件或采用自己的組件會變得單調乏味,無法繼續選擇。
在accent-color
之后,一行CSS為內置組件帶來了主題顏色,除了色調之外,瀏覽器還會智能地為組件的輔助部分選擇適當的對比色,并適應系統配色方案(亮暗)。
/*?為所有顏色著色?*/
:root?{accent-color:?hotpink;
}/*?為一個元素著色?*/
progress?{accent-color:?indigo;
}

相關資源
Spec: https://www.w3.org/TR/css-ui-4/#widget-accent
MDN: https://developer.mozilla.org/docs/Web/CSS/accent-color
web.dev: https://web.dev/accent-color/
Tint User-Interface Controls with CSS accent-color:https://www.bram.us/2021/08/23/tint-user-interface-controls-with-css-accent-color/
6. Color level 4 and 5
在過去的幾十年里,web 一直由 sRGB 主導,但在高清顯示器和預先配備 OLED 或 QLED 屏幕的移動設備不斷擴大的數字世界中,sRGB 是不夠的。此外,需要適應用戶偏好的動態頁面,并且顏色管理已成為設計師、設計系統和代碼維護人員日益關注的問題。
CSS有許多新的顏色功能和空間(不過不是在2022年):
達到顯示器高清色彩功能的色彩。
與意圖相匹配的色彩空間,例如感知一致性。
漸變的顏色空間會顯著改變插值結果。
顏色功能可幫助你混合和對比,并選擇在哪個空間進行工作。
在所有這些顏色特性出現之前,設計系統需要預先計算出適當的對比色,并確保調色板具有適當的活力,而預處理器或JavaScript則起到了重要作用。
在完成了所有這些顏色功能之后,瀏覽器和CSS可以動態、及時地完成所有工作。CSS可以進行編排和計算,而不是向用戶發送很大的CSS和JavaScript來啟用主題和數據可視化顏色。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);}
}
(1)hwb()
瀏覽器支持:

HWB代表色調、白度和黑度。它表現為一種對人類友好的表達顏色的方式,因為它只是一種色調,加上一定量的白色或黑色以使其變亮或變暗。
:root?{--hwb-swatch-1:?hwb(200?75%?0%);--hwb-swatch-2:?hwb(200?50%?25%);--hwb-swatch-3:?hwb(200?25%?50%);--hwb-swatch-4:?hwb(200?0%?75%);--hwb-swatch-5:?hwb(200?0%?90%);
}.swatch:nth-of-type(1)?{background:?var(--hwb-swatch-1);
}.swatch:nth-of-type(2)?{background:?var(--hwb-swatch-2);
}.swatch:nth-of-type(3)?{background:?var(--hwb-swatch-3);
}.swatch:nth-of-type(4)?{background:?var(--hwb-swatch-4);
}.swatch:nth-of-type(5)?{background:?var(--hwb-swatch-5);
}*?{box-sizing:?border-box;margin:?0;
}html?{block-size:?100%;
}body?{min-block-size:?100%;font-family:?system-ui,?sans-serif;display:?grid;
}
效果如下:

使用此顏色函數會產生來自 sRGB 顏色空間的顏色,與 HSL 和 RGB 相同。就 2022 年的新意而言,這并沒有給你帶來新的色彩,但它可能會讓語法和心智模型的粉絲更容易完成一些任務。
相關資源:
Spec: https://www.w3.org/TR/css-color-4/#the-hwb-notation
MDN: https://developer.mozilla.org/docs/Web/CSS/color_value/hwb()
hwb() – a color notation for humans?: https://www.stefanjudis.com/blog/hwb-a-color-notation-for-humans/
(2)顏色空間
顏色的表示方式是通過顏色空間完成的。每個顏色空間都為使用顏色提供了各種功能和權衡。有些人可能會將所有鮮艷的顏色打包在一起;有些人可能會先根據它們的亮度排列它們。
2022年, SS 將提供 10 個新的顏色空間,每個都有獨特的功能來幫助設計師和開發人員顯示、挑選和混合顏色。以前,sRGB 是處理顏色的唯一選項,但現在 CSS 釋放了新的潛力和新的默認顏色空間 LCH。
(3)color-mix()
瀏覽器支持:

在 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);
}
在 2022 年享受在你的樣式表中混合各種顏色空間的顏色!
相關資源:
Spec: https://www.w3.org/TR/css-color-5/#color-mix
MDN: https://developer.mozilla.org/docs/Web/CSS/color_value/color-mix()
Theming demo: https://codepen.io/argyleink/pen/WNoWadG
Another theming demo: https://codepen.io/argyleink/pen/YzZQYMq
Create a color theme with CSS Relative Color Syntax, CSS color-mix(), and CSS color-contrast(): https://www.bram.us/2021/04/28/create-a-color-theme-with-css-relative-color-syntax-css-color-mix-and-css-color-contrast/
(4)color-contrast()
瀏覽器支持:

在 color-contrast()
之前,樣式表作者需要提前了解可訪問的顏色。通常,調色板會在顏色樣本上顯示黑色或白色文本,以向顏色系統的用戶指示需要哪種文本顏色才能與該樣本進行適當對比。

在 color-contrast()
之后,樣式表作者可以將任務完全轉移到瀏覽器。你不僅可以使用瀏覽器自動選擇黑色或白色,還可以為其提供設計系統適用的顏色列表,并讓其選擇第一個通過所需對比度的顏色。
這是 HWB 調色板集 demo 的截圖,其中文本顏色由瀏覽器根據樣本顏色自動選擇:

語法的基本內容如下所示,其中灰色被傳遞給函數,瀏覽器確定黑色或白色是否具有最大對比度:
color:?color-contrast(gray);
該函數還可以使用顏色列表進行自定義,它將從中選擇對比度最高的顏色:
color:?color-contrast(gray?vs?indigo,?rebeccapurple,?hotpink);
最后,如果最好不要從列表中選擇對比度最高的顏色,可以提供目標對比度,并選擇第一種通過該對比度的顏色:
color:?color-contrast(var(--bg-blue-1)vsvar(--text-lightest),?var(--text-light),?var(--text-subdued)to?AA?/*?4.5?could?also?be?passed?*/
);
這個函數不僅可以用于文本顏色,但這將是它的主要用途。想一想,一旦選擇適當的對比色內置到 CSS 語言本身中,那么交付可訪問且易讀的界面將變得多么容易。
相關資源:
Spec: https://www.w3.org/TR/css-color-5/#colorcontrast
MDN: https://developer.mozilla.org/docs/Web/CSS/color_value/color-contrast()
Demo: https://codepen.io/web-dot-dev/pen/qBpzwZW
(5)相對顏色語法
瀏覽器支持:

在使用相對顏色語法之前,為了計算顏色并進行調整,需要將顏色通道單獨放置到自定義屬性中。這一限制還使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()
來確保標簽具有適當的對比度:

此函數也可用于調色板生成。這是一個例子,其中整個調色板是根據提供的基色生成的。這套 CSS 支持所有不同的調色板,每個調色板只是提供不同的基色。
: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);
}

到現在為止,希望你可以看到色彩空間和不同的色彩函數如何根據它們的優點和缺點用于不同的目的。
相關資源:
Spec: https://www.w3.org/TR/css-color-5/#relative-color-function
Palettes: https://codepen.io/web-dot-dev/pen/GRybLvm
Variants: https://codepen.io/web-dot-dev/pen/dyJBLWG
(6)漸變顏色空間
在漸變顏色空間之前,sRGB 是使用的默認顏色空間。sRGB 通常是可靠的,但確實有一些弱點,例如灰色死區。

在漸變顏色空間之后,告訴瀏覽器使用哪個顏色空間進行顏色插值。這使開發人員和設計人員能夠選擇他們喜歡的漸變。默認色彩空間也更改為 LCH 而不是 sRGB。
語法添加在漸變方向之后,使用新的in
語法,并且是可選的:
background-image:?linear-gradient(to?right?in?hsl,black,?white
);background-image:?linear-gradient(to?right?in?lch,black,?white
);
這是從黑色到白色的基本且必不可少的漸變。查看每個顏色空間中的結果范圍。有些更早達到深黑色,有些更晚達到白色。

在下一個示例中,黑色轉換為藍色,因為它是漸變的已知問題空間。大多數顏色空間在顏色插值期間會逐漸變為紫色。或者,當顏色在其顏色空間內從 A 點移動到 B 點時。由于漸變將從 A 點到 B 點采用直線,因此色彩空間的形狀變化極大地改變了路徑沿途的停止點。
okLCH 和 okLAB 是專門的色彩空間,可以解釋各種變化,比如這個變成紫色的,這使得它們對于漸變特別準確。

相關資源:
Spec: https://drafts.csswg.org/css-images-4/#linear-gradients
Codepen comparing gradients: https://codepen.io/argyleink/pen/OJObWEW
Observable notebook: https://observablehq.com/@argyleink/colorjs-notebook-fade-to-white
7. inert
瀏覽器支持:

在 inert
之前,將用戶的注意力引導到需要立即關注的頁面或應用程序區域是一種很好的做法。這種引導式焦點策略被稱為焦點捕獲,因為開發人員會將焦點置于交互空間中,監聽焦點更改事件,如果焦點離開交互空間,則強制返回。使用鍵盤或屏幕閱讀器的用戶會被引導回到互動空間,以確保在繼續完成之前的任務。
在inert
之后,不需要設置陷阱,因為你可以凍結或保護頁面或應用程序的整個部分。當文檔的這些部分處于惰性狀態時,單擊和焦點更改嘗試根本不可用。你也可以把它想象成守衛而不是陷阱,惰性分子不想讓你待在某個地方,而是讓其他地方不可用。
JavaScript alert()
函數就是一個很好的例子:

請注意,在調用 alert()
之前,頁面是如何通過鼠標和鍵盤訪問的。顯示警報對話框彈出窗口后,頁面的其余部分將被凍結或不活動。用戶的注意力放在警報對話框中,無處可去。一旦用戶交互并完成警報功能請求,頁面將再次交互。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
也有助于諸如滑出式側邊菜單用戶體驗之類的事情。當用戶滑出側邊菜單時,讓鼠標或鍵盤與后面的頁面交互是不合適的;相反,當顯示側邊菜單時,使頁面處于inert
狀態,現在用戶必須關閉或在該側邊菜單中導航,并且永遠不會發現自己在打開菜單的頁面中迷失在其他地方。
相關資源:
Spec: https://html.spec.whatwg.org/multipage/interaction.html#inert
MDN: https://developer.mozilla.org/docs/Web/API/HTMLElement/inert
Introducing inert: https://developer.chrome.com/blog/inert/
8. COLRv1 字體
在 COLRv1 字體之前,Web 有 OT-SVG 字體,這也是一種開放格式,用于漸變字體、內置顏色和效果。不過,它們可能會變得非常大,雖然它們允許編輯文本,但定制的空間不大。
在 COLRv1 字體之后,Web 具有更小的占用空間、矢量可縮放、可重新定位、漸變功能和混合模式驅動的字體,它們接受參數來自定義每個用例的字體或匹配主題。

下面是 Chrome Developer 博客文章中有關表情符號的示例。也許你已經注意到,如果你放大表情符號的字體大小,它就不會保持清晰。這是一個圖像,而不是矢量藝術。使用 COLRv1 字體,表情符號既矢量又漂亮:

圖標字體可以用這種格式做一些驚人的事情,提供自定義的雙色調調色板等等。加載 COLRv1 字體就像任何其他字體文件一樣:
@import?url(https://fonts.googleapis.com/css2?family=Bungee+Spice);
自定義 COLRv1 字體使用 @font-palette-values
完成的,這是一個特殊的 CSS 規則,用于將一組自定義選項分組和命名為一個包以供以后參考。指定自定義名稱就像自定義屬性一樣,以 --
開頭:
@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;
}

隨著越來越多的可變字體和彩色字體的出現,網頁排版正朝著豐富的定制和創造性表達的方向發展。
相關資源:
Github: https://github.com/googlefonts/colr-gradients-spec
Chrome Developers: https://developer.chrome.com/blog/colrv1-fonts/
BlinkOn developer explainer video: https://www.youtube.com/watch?v=BmqYm5Wwz8M
9. 視口單位

在新的視口變體之前,web提供了物理單位來幫助適應視口。有高度、寬度、最小尺寸 (vmin) 和最大邊 (vmax)。這些對很多事情都有效,但移動瀏覽器帶來了復雜性。
在移動設備上,加載頁面時,會顯示帶有 url 的狀態欄,此欄會占用部分視口空間。在幾秒鐘和一些交互之后,狀態欄可能會滑開,以便為用戶提供更大的視口體驗。但是當該條滑出時,視口高度發生了變化,任何 vh 單位都會隨著目標大小的變化而移動和調整大小。在后來的幾年里,vh 單位特別需要決定要使用兩種視口尺寸中的哪一種,因為這會在移動設備上造成不和諧的視覺布局問題。已確定 vh 將始終代表最大的視口。
.original-viewport-units?{height:?100vh;width:?100vw;--size:?100vmin;--size:?100vmax;
}
在新的視口變體之后,可以使用小型、大型和動態視口單位,并在物理視口單元的基礎上添加邏輯等效單位。這個想法是讓開發人員和設計人員能夠選擇他們想要在給定場景中使用的單位。當狀態欄消失時,也許可以稍微改變一下不協調的布局,這樣就可以不用擔心使用dvh(動態視口高度)。

以下是新視口變體提供的所有新視口單位選項的完整列表:
/*?高度視口單位?*/
.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;
}
希望這些將為開發人員和設計人員提供實現其視口響應式設計所需的靈活性。
相關資源:
Spec: https://drafts.csswg.org/css-values-4/#viewport-relative-lengths
The Large, Small, and Dynamic Viewports: https://www.bram.us/2021/07/08/the-large-small-and-dynamic-viewports/
10. :has()
瀏覽器支持:

在 :has()
之前,選擇器的主體總是在最后。例如,這個選擇器的主體是一個列表項:ul > li。偽選擇器可以改變選擇器,但它們不會改變主體:ul > li:hover
或 ul > 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()
看起來像父選擇器的例子。如果圖片有 <figcaption>
,請考慮 <figure>
元素內圖像的用例和調整圖像的樣式。在以下示例中,選擇帶有 figcaptions
的圖像,然后選擇該上下文中的圖像。使用:has()
不會改變主體,因為我們的目標是圖像而不是數字:
figure:has(figcaption)?img?{...}
使用 @supports
及其 selector()
函數使檢查支持變得簡單,該函數在使用之前測試瀏覽器是否支持該語法:
@supports?(selector(:has(works)))?{/*?safe?to?use?:has()?*/
}
相關資源:
Spec: https://www.w3.org/TR/selectors-4/#relational
MDN: https://developer.mozilla.org/docs/Web/CSS/:has
The CSS :has() selector is way more than a "parent selector": https://www.bram.us/2021/12/21/the-css-has-selector-is-way-more-than-a-parent-selector/
2022年及以后的功能
在所有這些令人驚嘆的功能在 2022 年登陸之后,仍有許多事情將難以完成。下面來介紹一些剩余的問題以及正在積極開發的解決方案。這些解決方案是實驗性的,即使它們可能在瀏覽器的標志后面被指定或可用。
1. 松散類型的自定義屬性
瀏覽器支持:

CSS 自定義屬性是驚人的。它們允許將各種事物存儲在命名變量中,然后可以對其進行擴展、計算、共享等。事實上,它們是如此靈活,如果有一些不太靈活的東西會更好。
考慮一個場景,其中長方體陰影使用自定義屬性作為其值:
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>
。這意味著陰影會繼續正常工作,即使為其自定義屬性之一提供了無效值。它沒有失敗,而是恢復到其初始值 0px
。
除了類型安全之外,它還為動畫打開了許多大門。CSS 語法的靈活性使得某些動畫變得不可能,比如漸變。@property
在這里會很有用,因為類型化的 CSS 屬性可以告知瀏覽器開發人員在其他過于復雜的插值中的意圖。它本質上限制了可能性的范圍,以至于瀏覽器可以為以前無法實現的樣式的各個方面設置動畫。
考慮下面的例子,其中使用徑向漸變來制作覆蓋的一部分,從而創建聚光燈聚焦效果。按下alt/opt
鍵時,JavaScript設置鼠標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;
}
瀏覽器現在能夠為漸變大小設置動畫,因為我們已將修改的表面積減少到只有一個屬性并設置值,以便瀏覽器可以智能地插入長度。
相關資源:
Spec: https://www.w3.org/TR/css-properties-values-api-1/#at-property-rule
MDN: https://developer.mozilla.org/docs/Web/CSS/@property
web.dev: https://web.dev/at-property/
Zoom demo: https://codepen.io/argyleink/pen/rNwWwor
CSS Tricks: https://css-tricks.com/exploring-property-and-its-animating-powers/
2. 媒體查詢范圍
在媒體查詢范圍之前,CSS 媒體查詢使用 min-width
和 max-width
來表達條件。它可能看起來像這樣:
@media?(min-width:?320px)?{…
}
在媒體查詢范圍之后,相同的媒體查詢可能如下所示:
@media?(320px?>=?width)?{…
}
使用 min-width
和 max-width
的 CSS 媒體查詢可能如下所示:
@media?(min-width:?320px)?and?(max-width:?1280px)?{…
}
在媒體查詢范圍之后,相同的媒體查詢可能如下所示:
@media?(320px?<=?width?<=?1280px)?{…
}
后者看起來會比前者更清晰。由于規范的增加,開發人員將能夠選擇他們喜歡的,甚至可以互換使用它們。
相關資源:
Spec: https://www.w3.org/TR/mediaqueries-5/#mq-range-context
MDN: https://developer.mozilla.org/docs/Web/CSS/Media_Queries/Using_media_queries#syntax_improvements_in_level_4
PostCSS plugin: https://github.com/postcss/postcss-media-minmax
3. 自定義媒體查詢
在@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?{…}
}
相關資源
Spec: https://www.w3.org/TR/mediaqueries-5/#custom-mq
PostCSS plugin: https://github.com/postcss/postcss-custom-media
4. 嵌套選擇器
在 @nest
之前,樣式表中有很多重復。當選擇器很長且每個選擇器都針對微小的差異時,它變得特別笨拙。所以,我們會經常使用預處理器的嵌套功能。
在 @nest
之后,重復就消失了。幾乎所有支持預處理器的嵌套功能都將內置在 CSS 中。
article?{color:?darkgray;
}article?>?a?{color:?var(--link-color);
}/*?with?@nest?becomes?*/article?{color:?darkgray;&?>?a?{color:?var(--link-color);}
}
除了避免重復的代碼,嵌套最重要的是樣式上下文保留在一個樣式塊中。讀者無需從一個選擇器及其樣式跳到另一個帶有樣式的選擇器(示例 1),而是可以留在文章的上下文中并查看文章在其中擁有鏈接。
考慮一個子組件,它希望在不同的父級上下文中調整自己,而不是父組件擁有樣式并更改子組件:
/*?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 總體上有助于更健康的風格組織、集中化和所有權。組件可以分組并擁有自己的樣式,而不是讓它們散布在其他樣式塊中。在這些示例中,它可能看起來很小,但為了方便和易讀性,它可以產生非常大的影響。
相關資源:
Spec: https://www.w3.org/TR/css-nesting-1/
PostCSS plugin: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
The future of CSS: Nesting Selectors: https://www.bram.us/2019/03/17/the-future-of-css-nesting-selectors/
5. 樣式范圍
在 @scope
之前,存在許多策略,因為 CSS 中的樣式在默認情況下是級聯、繼承和全局作用域的。CSS 的這些特性在很多方面都非常方便,但對于復雜的站點和應用程序,可能有許多不同樣式的組件,級聯的全局空間和性質會使樣式感覺像是在泄漏。
在 @scope
之后,樣式不僅可以限定在一個上下文中,就像一個類一樣,它們還可以明確樣式的結束位置,并且不會繼續級聯或繼承。
在以下示例中,BEM 命名約定范圍可以轉換為實際意圖。BEM 選擇器試圖將 header
元素的顏色范圍限定為具有命名約定的 .card
容器。這要求header
上有這個類名,從而完成目標。使用 @scope
,無需命名約定即可在不標記header
元素的情況下完成相同的目標:
.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;}
}
相關資源:
Spec: https://www.w3.org/TR/css-scoping-1/
Explainer: https://css.oddbird.net/scope/explainer/
6. 瀑布流布局
在使用Grid實現CSS瀑布流布局之前,JavaScript是實現瀑布流布局的最佳方式,因為任何帶有列或flexbox的CSS方法都會不準確地表示內容順序。使用grid構建CSS后,將不需要JavaScript庫,內容順序也將正確。

上圖使用以下 CSS 實現:
.container?{display:?grid;grid-template-columns:?repeat(4,?1fr);grid-template-rows:?masonry;
}
相關資源:
Spec: https://drafts.csswg.org/css-grid-3/#masonry-layout-algorithm
MDN: https://developer.mozilla.org/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout
Smashing Magazine: https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/
7. CSS保存數據
在 prefers-reduced-data
媒體查詢之前,JavaScript 和服務器可以根據用戶的操作系統或瀏覽器的“data saver”選項更改其行為,但 CSS 不能。
在 prefers-reduced-data
媒體查詢之后,CSS 可以加入用戶體驗增強,并在保存數據方面發揮作用。
@media?(prefers-reduced-data:?reduce)?{picture,?video?{display:?none;}
}
在這個媒體滾動組件中使用了前面的CSS,節省了很多資源。根據訪問視口的大小,可以在頁面加載上節省更多資源。當用戶與媒體滾動條交互時,繼續保存。這些圖像上都有load="lazy"
屬性,再加上CSS完全隱藏元素,這意味著永遠不會對圖像發出網絡請求。

對于我的測試,在一個中等大小的視口上,最初加載了 40 個請求和 700kb 的資源。當用戶滾動媒體選擇時,會加載更多請求和資源。使用 CSS prefers-reduced-data
媒體查詢,加載了 10 個請求和 172kb 的資源。這節省了半兆字節,用戶甚至沒有滾動任何媒體,此時沒有其他請求。

這種減少數據體驗的優勢不僅僅是節省資源。可以看到更多標題,并且沒有分散注意力的封面圖片來吸引注意力。許多用戶在數據保護模式下瀏覽,因為他們按每兆字節的數據付費——很高興看到 CSS 能夠在這里提供幫助。
相關資源:
Spec: https://www.w3.org/TR/mediaqueries-5/#prefers-reduced-data
MDN: https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-data
GUI Challenges: https://gui-challenges.web.app/media-scroller/dist/
Smashing Magazine: https://www.smashingmagazine.com/2021/12/core-web-vitals-case-study-smashing-magazine/#savedata-and-prefers-reduced-data
8. 滾動快照
在這些滾動快照提案之前,需要編寫自己的 JavaScript 來管理輪播、滑塊或圖庫,并且可能會很復雜,需要所有的觀察者和狀態管理。此外,如果不小心,自然滾動速度可能會被腳本標準化,使用戶交互感覺有點不自然并且可能很笨拙。
(1)snapChanging()
瀏覽器一發布快照子項,就會觸發此事件。這允許用戶界面反映缺少快照子項和滾動條的不確定快照狀態,因為它現在正在使用,并將在新的地方落地。
document.querySelector('.snap-carousel').addEventListener('snapchanging',?event?=>?{console.log('Snap?is?changing',?event.snappedTargetsList);
});
(2)snapChanged()
一旦瀏覽器捕捉到一個新的子對象,滾動條停止,就會觸發此事件。這使得任何依賴于快照子對象的UI都可以更新并反映連接。
document.querySelector('.snap-carousel').addEventListener('snapchanged',?event?=>?{console.log('Snap?changed',?event.snappedTargetsList);
});
(3)scroll-start
滾動并不總是從一開始就開始。考慮一下可滑動組件,其中向左或向右滑動會觸發不同的事件,或者頁面加載時的搜索欄最初是隱藏的,直到滾動到頂部。這個CSS屬性允許開發者指定一個滾動條應該從一個特定的點開始。
:root?{?--nav-height:?100px?}.snap-scroll-y?{scroll-start-y:?var(--nav-height);
}
(4):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。
相關資源:
Draft spec: https://drafts.csswg.org/css-scroll-snap-2/
Explainers: https://github.com/argyleink/ScrollSnapExplainers/blob/main/css-snap-target/readme.md
Snap demos: https://snap-gallery.netlify.app/
9. CSS狀態
在 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 中,希望能以更清晰、更語義化的方式來編排交互和狀態。
相關資源:
Draft: https://tabatkins.github.io/css-toggle/
The Future of CSS: CSS Toggles: https://www.bram.us/2022/04/20/the-future-of-css-css-toggles/
10. 自定義選擇元素
在 <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;
}

相關資源:
Spec: https://open-ui.org/prototypes/selectmenu
Demo: https://microsoftedge.github.io/Demos/selectmenu/
11. 定位
在 anchor()
之前,絕對位置和相對位置是為開發人員提供的位置策略,可以讓子元素在父元素中移動。
在 anchor(
) 之后,開發人員可以將元素定位到其他元素,無論它們是否是子元素。它還允許開發人員指定要定位的邊緣,以及創建元素之間位置關系的其他細節。
相關資源:
Explainer: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/CSSAnchoredPositioning/explainer.md
原文:https://web.dev/state-of-css-2022/
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經堅持寫了8年,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助4000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
掃碼加我微信 ruochuan02、拉你進源碼共讀群
今日話題
目前建有江西|湖南|湖北?籍 前端群,想進群的可以加我微信 ruochuan12?進群。分享、收藏、點贊、在看我的文章就是對我最大的支持~