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