Google I/O 2023:最新 CSS 特性解讀!
當今的前端開發(fā)正呈現(xiàn)出越來越多的特性,新的 CSS 特性也隨之不斷涌現(xiàn)。在近日的 2023 Google I/O 大會上,有很多新的 CSS 特性被介紹,讓我們一起來看看這些最新的功能吧!
以下是最近推出或即將推出的 20 個最令人興奮的 CSS 功能:
- 容器查詢
- 樣式查詢
- :has()
- nth-of
- text-wrap: balance
- initial-letter
- 動態(tài)視口單位
- 廣色域顏色空間
- color-mix()
- 嵌套
- 級聯(lián)層
- 作用域樣式
- 三角函數(shù)
- 單個變換屬性
- popover
- 定位錨點
- selectmenu
- 離散屬性過渡
- 滾動驅動的動畫
- View transitions
新的響應式
容器查詢
瀏覽器支持:
容器查詢最近在所有現(xiàn)代瀏覽器中已經(jīng)穩(wěn)定。它允許查詢父元素的大小和樣式,以確定應應用于其任何子元素的樣式。媒體查詢只能訪問和利用視口的信息,它是一種更精確的工具,可以支持任意數(shù)量的布局或嵌套布局。
在下面的收件箱示例中,主收件箱和收藏夾側邊欄都是容器。它們內部的電子郵件根據(jù)可用空間調整其網(wǎng)格布局,并根據(jù)需要顯示或隱藏電子郵件時間戳。
因為有了容器查詢,這些組件的樣式都是動態(tài)的。 如果調整頁面大小和布局,組件將響應它們單獨分配的空間。 側邊欄變成了一個有更多空間的頂部欄,布局看起來更像主收件箱。當空間較少時,它們都以緊湊的格式顯示。
樣式查詢
瀏覽器支持:
容器查詢規(guī)范還允許查詢父容器的樣式。這目前在 Chrome 111 中部分實現(xiàn),可以在其中使用 CSS 自定義屬性來應用容器樣式。以下示例使用存儲在自定義屬性值中的天氣特征(例如下雨、晴天和多云)來設置卡片背景和指示器圖標的樣式。
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
這只是樣式查詢的開始。將來,將使用布爾查詢來確定自定義屬性值是否存在并減少代碼重復,目前正在討論的是范圍查詢,以根據(jù)值的范圍應用樣式。這樣就可以使用下雨或云層覆蓋幾率的百分比值來應用此處顯示的樣式。
:has()
瀏覽器支持:
:has() 選擇器是現(xiàn)代瀏覽器中最強大的新 CSS 功能之一。 使用 :has()可以通過檢查父元素是否包含特定子元素或這些子元素是否處于特定狀態(tài)來應用樣式,也就是父選擇器。
在容器查詢示例的基礎上,可以使用 :has() 使組件更加動態(tài)。 其中,帶有“??”元素的項目會應用灰色背景,而帶有選中復選框的項目會應用藍色背景。
此 API 不限于父級選擇,還可以為父級中的任何子級設置樣式。 例如,當項目具有 ?? 元素時,標題為粗體。 這是通過 .item:has(.star) .title 完成的。 使用 :has() 選擇器可以訪問父元素、子元素,甚至兄弟元素,這使它成為一個非常靈活的 API。
nth-of
瀏覽器支持:
Web 平臺現(xiàn)在有更高級的第 n 個子元素選擇。 高級 nth-child 語法提供了一個新關鍵字(“of”),它允許使用現(xiàn)有的 An+B 語法,并在其中搜索更具體的子集。
如果使用常規(guī)的 nth-child,例如 :nth-child(2) 在特殊類上,瀏覽器將選擇應用了特殊類的元素,也是第二個子元素。 這與 :nth-child(2 of .special) 形成對比,后者將首先預過濾所有 .special 元素,然后從該列表中選擇第二個。
:nth-child(2 of .highlight) {
outline: 0.3rem dashed hotpink;
outline-offset: 0.7rem;
}
text-wrap: balance
從 Chrome 114 開始,可以使用 text-wrap 屬性并設置 balance 值,對標題使用文字自動換行平衡技術實現(xiàn)排版。
為了平衡文本,瀏覽器有效地對最小寬度執(zhí)行二進制搜索,這不會導致任何額外的行,在一個 CSS 像素(不是顯示像素)處停止。 為了進一步減少二進制搜索中的步驟,瀏覽器從平均線寬的 80% 開始。
initial-letter
initial-letter 屬性可以更好地控制內嵌首字下沉樣式??梢栽?first-letter偽元素上使用initial-letter指定以下內容:基于字母占據(jù)的行數(shù),來指定字母的大小。字母的塊偏移量或“下沉”,來指定字母所在位置。
動態(tài)視口單位
瀏覽器支持:
Web開發(fā)人員面臨的一個常見問題是在移動設備上實現(xiàn)準確和一致的全視口大小。作為開發(fā)者,希望100vh(視口高度的100%)指的是“與視口一樣高”,但vh單位無法考慮到移動設備上縮回的導航欄之類的因素,因此有時它會太長并導致頁面滾動。
為了解決這個問題,現(xiàn)在Web平臺上有新的單位值,包括:
- 小視口高度和寬度(svh和svw),表示最小活動視口大小。
- 大視口高度和寬度(lvh和lvw),表示最大活動視口大小。
- 動態(tài)視口高度和寬度(dvh和dvw)。
當額外的動態(tài)瀏覽器工具欄(例如頂部地址或底部選項卡欄)可見或不可見時,動態(tài)視口單位的值會發(fā)生變化。
廣色域顏色空間
Web 平臺的另一個重要新增功能是廣色域色彩空間。 在 Web 平臺上提供廣色域顏色之前,可以拍出色彩鮮艷的照片,可以在現(xiàn)代設備上查看,但無法獲得按鈕、文本顏色或背景來匹配這些鮮艷的值。
現(xiàn)在在 Web 平臺上有一系列新的顏色空間,包括 REC2020、P3、XYZ、LAB、OKLAB、LCH和OKLCH。
可以在 DevTools 中看到顏色范圍是如何擴展的,那條白線標示出 sRGB 范圍的結束位置和廣色域顏色范圍的開始位置。
color-mix()
瀏覽器支持:
color-mix() 函數(shù)支持混合兩個顏色值,基于顏色通道創(chuàng)建新值。混合顏色的顏色空間會影響結果。在更感知的顏色空間(如oklch)中工作時,將經(jīng)過與sRGB等不同的顏色范圍。
color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);
color-mix()函數(shù)提供了一個備受期待的功能:在保留不透明顏色值的同時,添加一些透明度?,F(xiàn)在,可以在不同的不透明度下使用品牌顏色變量創(chuàng)建這些顏色的變體。方法是將顏色與透明混合。當將品牌顏色藍色與10%透明度混合時,會得到一個90%不透明的品牌顏色。
現(xiàn)在可以在 Chrome DevTools 中看到這一點,在樣式窗格中有一個非常漂亮的預覽維恩圖圖標。
CSS基礎
CSS 嵌套
瀏覽器支持:
CSS嵌套是Sass中很受歡迎的功能,也是多年來CSS開發(fā)人員最重要的需求之一,現(xiàn)在終于出現(xiàn)在 Web 平臺上。嵌套允許開發(fā)人員以更簡潔、分組的格式編寫代碼,減少冗余。
.card {}
.card:hover {}
/* 嵌套 */
.card {
&:hover {
}
}
我們還可以嵌套媒體查詢,這也意味著可以嵌套容器查詢。在下面的示例中,如果卡片容器足夠寬度,卡片將從縱向布局更改為橫向布局:
.card {
display: grid;
gap: 1rem;
@container (width >= 480px) {
display: flex;
}
}
當容器有更多(或等于)480px 的可用行內空間時,就會發(fā)生對 flex 的布局調整。 當條件滿足時,瀏覽器將簡單地應用新的顯示樣式。
級聯(lián)層
瀏覽器支持:
開發(fā)人員另一個痛點是確保樣式勝過其他樣式的一致性,解決這個問題的一個部分是更好地控制 CSS 級聯(lián)。級聯(lián)層通過讓用戶控制哪些層比其他層具有更高的優(yōu)先級來解決這個問題,這意味著可以更好地控制何時應用樣式。
作用域
瀏覽器支持:
CSS 作用域樣式允許開發(fā)人員指定應用特定樣式的邊界,本質上是在 CSS 中創(chuàng)建原生命名空間。 以前,開發(fā)人員依靠第 3 方腳本來重命名類,或特定的命名約定來防止樣式?jīng)_突,但很快,可以使用 @scope。
這里將 .title 元素限定為 .card。 這將防止該 title 元素與頁面上的任何其他 .title 元素發(fā)生沖突,例如博客文章標題或其他標題。
@scope (.card) {
.title {
font-weight: bold;
}
}
三角函數(shù)
瀏覽器支持:
CSS的另一個新功能是將三角函數(shù)添加到現(xiàn)有的CSS數(shù)學函數(shù)中。這些函數(shù)現(xiàn)在在所有現(xiàn)代瀏覽器中都是穩(wěn)定的,并使您能夠在Web平臺上創(chuàng)建更有機的布局。一個很好的例子是這個徑向菜單布局,現(xiàn)在可以使用sin()和cos()函數(shù)進行設計和動畫。
在下面的示例中,點圍繞中心點旋轉。每個點不是圍繞其自身的中心旋轉然后向外移動,而是在 X 和 Y 軸上平移。 X 軸和 Y 軸上的距離分別通過考慮 --angle 的 cos() 和 sin() 來確定。
、
單個變換屬性
過去,需要依賴變換函數(shù)來應用子函數(shù)來縮放、旋轉和平移 UI 元素。這涉及大量重復工作,并且在動畫中的不同時間應用多個變換時尤其令人沮喪。
.target {
transform: translateX(50%) rotate(30deg) scale(1.2);
}
.target:hover {
transform: translateX(50%) rotate(30deg) scale(2); /* Only scale changed here, yet you have to repeat all other parts */
}
現(xiàn)在,可以通過分離變換類型并單獨應用它們來在 CSS 動畫中擁有所有這些細節(jié)。
.target {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
.target:hover {
scale: 2;
}
這樣,平移、旋轉或縮放的變化可以在動畫期間的不同時間以不同的變化率同時發(fā)生。
可定制的組件
為了確保通過 Web 平臺解決一些關鍵的開發(fā)人員需求,正在與 OpenUI 社區(qū)小組合作,并確定了三個解決方案:
- 具有事件處理程序、聲明性DOM結構和可訪問默認值的內置彈出功能。
- 用于將兩個元素連接在一起以啟用錨定定位的CSS API。
- 可自定義下拉菜單組件,用于想要在選擇框內部樣式化內容的情況。
Popover
popover API 為元素提供了一些內置的瀏覽器支持,例如:
- 支持頂層,因此不必管理 z-index。 當打開彈出窗或對話框時,將該元素提升到頁面頂部的特殊層。
- 當在元素外部單擊時,彈出窗口將被關閉,從可訪問性樹中刪除,并正確管理焦點。
這一切意味著可以編寫更少的 JavaScript 來創(chuàng)建所有這些功能并跟蹤所有這些狀態(tài)。
popover 的 DOM 結構是聲明性的,可以像給 popover 元素一個 id 和 popover 屬性一樣清晰地編寫。 然后,將該 id 同步到將打開彈出窗的元素,例如具有 popovertarget 屬性的按鈕:
<div id="event-popup" popover>
<!-- Popover 內容 -–>
</div>
<button popovertarget="event-popup">Create New Event</button>
popover 是 popover=auto 的簡寫。具有 popover=auto 的元素在打開時會強制關閉其他彈出窗口,并接收焦點,并且可以進行輕型取消操作。相反,popover=manual元素不會強制關閉任何其他元素類型,也不會立即接收焦點,并且不支持輕型取消。它們通過切換或其他關閉操作關閉。
錨點定位
彈出框也經(jīng)常用在對話框和工具提示等元素中,這些元素通常需要錨定到特定元素。以這個事件為例。 當單擊日歷事件時,單擊的事件附近會出現(xiàn)一個對話框。日歷項是錨點,彈出窗口是顯示事件詳細信息的對話框。
我們可以使用 anchor() 函數(shù)創(chuàng)建一個居中的工具提示,使用錨點的寬度將工具提示定位在錨點 x 位置的 50% 處。 然后,使用現(xiàn)有的定位值來應用其余的放置樣式。
但是,如果彈出窗口根據(jù)定位方式不適合視口,會發(fā)生什么情況?
為了解決這個問題,錨點定位 API 包含可以自定義的后備位置。以下示例創(chuàng)建了一個名為top-then-bottom的后備位置。 瀏覽器將首先嘗試將工具提示定位在頂部,如果不適合視口,瀏覽器會將其定位在底部的錨定元素下方。
.center-tooltip {
position-fallback: --top-then-bottom;
translate: -50% 0;
}
@position-fallback --top-then-bottom {
@try {
bottom: calc(anchor(top) + 0.5rem);
left: anchor(center);
}
@try {
top: calc(anchor(bottom) + 0.5rem);
left: anchor(center);
}
}
<selectmenu>
通過彈出框和錨點定位,可以構建完全可定制的選擇菜單。 OpenUI 社區(qū)小組一直在研究這些菜單的基本結構,并尋找允許自定義其中任何內容的方法。 以下圖為例:
要構建最左側的選擇菜單示例,彩色點對應于日歷事件中顯示的顏色,可以按如下方式編寫:
<selectmenu>
<button slot="button" behavior="button">
<span>Select event type</span>
<span behavior="selected-value" slot="selected-value"></span>
<span><img src="icon.svg"/></span>
</button>
<option value="meeting">
<figure class="royalblue"></figure>
<p>Meeting</p>
</option>
<option value="break">
<figure class="gold"></figure>
<p>Lunch/Break</p>
</option>
...
</selectmenu>
離散屬性過渡
為了使所有這些彈出式窗口平穩(wěn)地切換進入和退出,Web 需要一些方法來為離散屬性設置動畫。作為為彈出窗、選擇菜單甚至現(xiàn)有元素(如對話框或自定義組件)啟用良好過渡的工作的一部分,瀏覽器正在用新的方式來支持這些動畫。
下面的 popover 演示使用 :popover-open 來展示打開狀態(tài),@initial 展示打開之前的狀態(tài),并在開啟后關閉狀態(tài)下直接將一個transform值應用于元素。為使此功能與display一起使用,它需要添加到transition屬性中,如下所示:
.settings-popover {
&:popover-open {
/* 0. before-change */
@initial {
transform: translateY(20px);
opacity: 0;
}
/* 1. open (changed) state */
transform: translateY(0);
opacity: 1;
}
/* 2. After-change state */
transform: translateY(-50px);
opacity: 0;
/* enumarate transitioning properties, including display */
transition: transform 0.5s, opacity 0.5s, display 0.5s;
}
交互
滾動驅動的動畫
瀏覽器支持:
滾動驅動的動畫允許根據(jù)滾動容器的滾動位置來控制動畫的播放。 這意味著當向上或向下滾動時,動畫會向前或向后滑動。 此外,使用滾動驅動的動畫,還可以根據(jù)元素在其滾動容器中的位置來控制動畫。這就可以創(chuàng)建有趣的效果,例如視差背景圖像、滾動進度條和在進入視圖時自動顯示的圖像。
此 API 支持一組 JavaScript 類和 CSS 屬性,可以輕松創(chuàng)建聲明式滾動驅動的動畫。
要通過滾動來驅動 CSS 動畫,可以使用新的 scroll-timeline、view-timeline 和 animation-timeline 屬性。要驅動 JavaScript Web 動畫 API,可以將 ScrollTimeline 或 ViewTimeline 實例作為時間軸選項傳遞給 Element.animate()。
這些新的 API 與現(xiàn)有的 Web Animations 和 CSS Animations API 結合使用,這意味著它們可以從這些 API 的優(yōu)勢中獲益。這包括讓這些動畫脫離主線程運行的能力。現(xiàn)在可以擁有絲般流暢的動畫,由滾動驅動,脫離主線程運行,只需幾行額外的代碼。
View transitions
瀏覽器支持:
View Transition API 可以輕松地一步更改 DOM,同時在兩種狀態(tài)之間創(chuàng)建動畫轉換。 這些可以是視圖之間的簡單淡入淡出,但也可以控制頁面各個部分的過渡方式。
View Transitions 可以用作漸進式增強:將更新DOM的代碼使用 View Transition API 包裝起來,并為不支持該功能的瀏覽器提供回退方案。
function spaNavigate(data) {
// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
updateTheDOMSomehow(data);
return;
}
// With a transition:
document.startViewTransition(() => updateTheDOMSomehow(data));
}
過渡應該是什么樣子是通過 CSS 控制的:
@keyframes slide-from-right {
from { opacity: 0; transform: translateX(75px); }
}
@keyframes slide-to-left {
to { opacity: 0; transform: translateX(-75px); }
}
::view-transition-old(root) {
animation: 350ms both slide-to-left ease;
}
::view-transition-new(root) {
animation: 350ms both slide-from-right ease;
}
View Transitions 目前適用于 Chrome 111 中的單頁應用 (SPA),多頁應用支持正在開發(fā)中。
參考:https://developer.chrome.com/blog/whats-new-css-ui-2023/