2024年,一大波 Web 新功能來(lái)襲!
2024年,Web UI 正迎來(lái)其前所未有的黃金時(shí)代,瀏覽器中涌現(xiàn)出眾多革新的 Web 功能,它們正以前所未有的速度重塑我們構(gòu)建Web應(yīng)用的方式,引領(lǐng)著全新的 Web 體驗(yàn)浪潮。接下來(lái),本文將深入探索這些令人矚目的新功能。
全新互動(dòng)體驗(yàn)
滾動(dòng)驅(qū)動(dòng)動(dòng)畫
滾動(dòng)驅(qū)動(dòng)動(dòng)畫是一種 CSS 動(dòng)畫,它將動(dòng)畫的進(jìn)度與滾動(dòng)事件相關(guān)聯(lián),使得動(dòng)畫效果可以根據(jù)用戶滾動(dòng)頁(yè)面的行為來(lái)觸發(fā)和控制。這種動(dòng)畫類型利用了CSS中的animation-timeline屬性,它可以創(chuàng)建與滾動(dòng)進(jìn)度或視圖變化相關(guān)的自定義時(shí)間線。
例如:
圖片
滾動(dòng)驅(qū)動(dòng)動(dòng)畫的類型包括:
- 默認(rèn)文檔時(shí)間線:這是 CSS 動(dòng)畫傳統(tǒng)上使用的時(shí)間線,隨著文檔加載后時(shí)間的流逝而進(jìn)展。
- 滾動(dòng)進(jìn)度時(shí)間線:這種時(shí)間線通過(guò)滾動(dòng)一個(gè)可滾動(dòng)元素來(lái)進(jìn)展。滾動(dòng)位置轉(zhuǎn)換為進(jìn)度百分比,從0%開始到100%結(jié)束。
- 視圖進(jìn)度時(shí)間線:這種時(shí)間線基于元素(稱為subject)在滾動(dòng)器中的可見(jiàn)性變化來(lái)進(jìn)展。默認(rèn)情況下,當(dāng)subject首次在滾動(dòng)器的一端可見(jiàn)時(shí),時(shí)間線為 0%,當(dāng)它滾動(dòng)到另一端時(shí)為100%。
例如,有一個(gè)圖片畫廊,希望當(dāng)用戶滾動(dòng)到圖片時(shí),圖片能夠逐漸淡入顯示:
<div class="gallery">
<div class="image-wrapper">
<img src="image1.jpg" class="gallery-image">
</div>
<div class="image-wrapper">
<img src="image2.jpg" class="gallery-image">
</div>
<!-- 更多圖片 -->
<div class="scroll-stretcher"></div> <!-- 強(qiáng)制產(chǎn)生滾動(dòng)條 -->
</div>
為.gallery-image類設(shè)置animation-timeline屬性為scroll(),這將創(chuàng)建一個(gè)匿名的滾動(dòng)進(jìn)度時(shí)間線,當(dāng)用戶滾動(dòng)畫廊時(shí),圖片會(huì)根據(jù)其在滾動(dòng)容器中的進(jìn)度逐漸淡入,透明度從0變?yōu)?,即完全可見(jiàn)。
.gallery {
position: relative;
height: 500px; /* 固定高度以產(chǎn)生滾動(dòng)條 */
overflow-y: scroll;
}
.image-wrapper {
height: 300px; /* 圖片容器高度 */
position: relative;
}
.gallery-image {
width: 100%;
height: auto;
opacity: 0; /* 初始透明度為0,即完全透明 */
animation-name: fade-in;
animation-duration: 1s;
animation-fill-mode: forwards; /* 動(dòng)畫完成后保持最終狀態(tài) */
/* 指定滾動(dòng)時(shí)間線,這里使用匿名時(shí)間線 */
animation-timeline: scroll();
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.scroll-stretcher {
height: 2000px; /* 強(qiáng)制內(nèi)容超出容器高度,產(chǎn)生滾動(dòng)條 */
}
瀏覽器支持:
圖片
視圖過(guò)渡
視圖過(guò)渡是一個(gè)全新 Web API,它提供了一種更簡(jiǎn)便的方法來(lái)在 DOM 狀態(tài)之間創(chuàng)建動(dòng)畫效果,甚至可以在頁(yè)面加載之間實(shí)現(xiàn)動(dòng)畫效果。在 Chromium 126 中提供了多頁(yè)面應(yīng)用的跨文檔視圖過(guò)渡支持。
例如:
圖片
假設(shè)有一個(gè)網(wǎng)頁(yè),其中包含多個(gè)<section>元素,希望當(dāng)用戶滾動(dòng)頁(yè)面時(shí),這些<section>元素能夠以不同的動(dòng)畫效果進(jìn)入和退出視口。
<section class="view-transition" id="section1">Section 1 Content</section>
<section class="view-transition" id="section2">Section 2 Content</section>
所有<section>元素定義一個(gè)共同的view-transition-name,這樣它們就可以參與到相同的視圖轉(zhuǎn)換中。使用@keyframes定義兩個(gè)動(dòng)畫效果:enterViewport和exitViewport,分別用于元素進(jìn)入和退出視口時(shí)的動(dòng)畫。通過(guò)animation-name將進(jìn)入視口的動(dòng)畫效果應(yīng)用到.view-transition類上。當(dāng)用戶滾動(dòng)頁(yè)面,使得<section>元素進(jìn)入或退出視口時(shí),相應(yīng)的動(dòng)畫效果將被觸發(fā)。
.view-transition {
/* 定義視圖轉(zhuǎn)換名稱 */
view-transition-name: section-transition;
/* 其他樣式... */
}
/* 定義進(jìn)入視口時(shí)的動(dòng)畫效果 */
@keyframes enterViewport {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 定義退出視口時(shí)的動(dòng)畫效果 */
@keyframes exitViewport {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(20px);
}
}
/* 應(yīng)用動(dòng)畫到視圖轉(zhuǎn)換 */
.view-transition {
animation-name: enterViewport;
animation-fill-mode: both;
animation-duration: 1s;
}
瀏覽器支持:
圖片
全新 UI 組件
Popover API
Popover API 是一種新的Web API,旨在簡(jiǎn)化創(chuàng)建和管理彈出式交互的復(fù)雜性,用于在網(wǎng)頁(yè)上創(chuàng)建和管理浮動(dòng)內(nèi)容(也稱為彈出框、彈出窗口或氣泡提示)的接口或技術(shù)。
在 HTML 中可以使用popover屬性將一個(gè)元素標(biāo)記為彈出框,并為其設(shè)置一個(gè) id:
<div id="simple-popover" popover>
前端充電寶
</div>
可以使用一個(gè)按鈕來(lái)控制這個(gè)彈出框,使用popovertarget屬性指向彈出框的 id 即可完成綁定:
<button popovertarget="simple-popover">打開彈出框</button>
還可以通過(guò)控制 popovertargetaction 屬性的值來(lái)控制 popover 的行為:hide(隱藏)、show(顯示)或默認(rèn)的toggle(切換)。
上面例子的效果如下,我們可以自己定義彈出框的樣式和行為:
圖片
瀏覽器支持:
圖片
錨點(diǎn)定位
CSS 錨點(diǎn)定位 API 允許原生地將元素相對(duì)于其他元素(稱為錨點(diǎn))進(jìn)行定位。錨點(diǎn)定位提供了一種強(qiáng)大的工具,用于構(gòu)建復(fù)雜的用戶界面,如菜單、子菜單、工具提示、彈出框(popover)、對(duì)話框(dialog)、卡片等,這些元素需要相對(duì)于頁(yè)面上的其他元素進(jìn)行精確放置。
例如,讓對(duì)話框始終放在點(diǎn)擊按鈕的正下方:
圖片
假設(shè)有一個(gè)按鈕(錨點(diǎn)),當(dāng)用戶點(diǎn)擊該按鈕時(shí),想要在頁(yè)面上顯示一個(gè)消息框(作為定位元素),并且該消息框應(yīng)該出現(xiàn)在按鈕的正下方。首先,需要給按鈕元素添加一個(gè) anchor-name 屬性,為其指定一個(gè)唯一的標(biāo)識(shí)符。
<button class="anchor-button" anchor-name="my-anchor">點(diǎn)擊我</button>
然后,在 CSS 中,可以使用 position-anchor 屬性或 anchor() 函數(shù)將消息框與錨點(diǎn)關(guān)聯(lián)起來(lái),并指定其位置。
.anchored-message {
position-anchor: my-anchor; /* 隱式錨點(diǎn) */
position: absolute;
top: 100%; /* 相對(duì)于錨點(diǎn)的底部 */
left: 0; /* 相對(duì)于錨點(diǎn)的左側(cè) */
/* 其他樣式... */
}
或者,使用 anchor() 函數(shù)進(jìn)行更復(fù)雜的定位:
.anchored-message {
position: absolute;
top: anchor(bottom) + 10px; /* 相對(duì)于錨點(diǎn)底部下方 10px */
left: anchor(left); /* 相對(duì)于錨點(diǎn)左側(cè) */
/* 其他樣式... */
}
瀏覽器支持:
圖片
獨(dú)占式手風(fēng)琴
實(shí)現(xiàn)手風(fēng)琴組件時(shí)需要將幾個(gè)<details>元素組合在一起,通過(guò)視覺(jué)分組來(lái)表明它們之間的聯(lián)系。在 Chrome 120 中,引入了一項(xiàng)新功能,即在<details>元素上支持name屬性。使用這個(gè)屬性時(shí),具有相同名稱值的多個(gè)<details>元素會(huì)形成一個(gè)語(yǔ)義組合。該組合中最多只能打開一個(gè)元素:當(dāng)打開該組合中的一個(gè)<details>元素時(shí),之前打開的一個(gè)將自動(dòng)關(guān)閉,這種手風(fēng)琴稱為獨(dú)占式手風(fēng)琴。
<details name="my-accordion">
<summary>Summary 1</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas delectus quibusdam, eum, aperiam sunt non dolorum pariatur molestias suscipit aut quia quas vero, illo quisquam nostrum sequi excepturi. Aliquam, obcaecati?</p>
</details>
<details name="my-accordion" open>
<summary>Summary 2</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas delectus quibusdam, eum, aperiam sunt non dolorum pariatur molestias suscipit aut quia quas vero, illo quisquam nostrum sequi excepturi. Aliquam, obcaecati?</p>
</details>
<details name="my-accordion">
<summary>Summary 3</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas delectus quibusdam, eum, aperiam sunt non dolorum pariatur molestias suscipit aut quia quas vero, illo quisquam nostrum sequi excepturi. Aliquam, obcaecati?</p>
</details>
作為獨(dú)占式手風(fēng)琴的一部分的<details>元素不一定需要是兄弟元素,它們可以散布在文檔任意位置。
瀏覽器支持:
圖片
:user-valid 和 :user-invalid
:user-valid 和 :user-invalid 偽類的行為類似于 :valid 和 :invalid,但只有在用戶與輸入進(jìn)行了重要交互之后,才匹配表單控件。即使用戶尚未開始與頁(yè)面進(jìn)行交互,必填但是空的表單控件將匹配 :invalid。只有當(dāng)用戶更改輸入并將其保留在無(wú)效狀態(tài)時(shí),該控件才會(huì)匹配 :user-invali。有了這兩個(gè)偽類,就不再需要編寫有狀態(tài)的代碼來(lái)跟蹤用戶已更改的輸入。
input:user-valid,
select:user-valid,
textarea:user-valid {
--state-color: green;
--bg: linear-gradient(45deg in oklch, lime, #02c3ff);
}
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
--state-color: red;
--bg: linear-gradient(15deg in oklch, #ea00ff, #ffb472);
}
瀏覽器支持:
field-sizing: content
field-sizing用于控制表單輸入元素(如輸入框input和文本域textarea)的尺寸調(diào)整方式,當(dāng)為輸入框或文本域設(shè)置field-sizing: content;時(shí),這些元素的大小會(huì)根據(jù)用戶輸入的內(nèi)容自動(dòng)調(diào)整。
textarea {
field-sizing: content;
width: 200px; /* 可以設(shè)置一個(gè)固定的寬度 */
min-height: 40px; /* 可以設(shè)置一個(gè)最小高度,以防止元素過(guò)小 */
}
瀏覽器支持:
在下拉菜單中添加分隔線
在<select>元素中使用<hr>是一項(xiàng)小而實(shí)用的特性,用于在選擇列表中清晰分隔內(nèi)容。
<label for="major-select">Please select a major:</label> <br/>
<select name="majors" id="major-select">
<option value="">Select a major</option>
<hr>
<option value="arth">Art History</option>
<option value="finearts">Fine Arts</option>
<option value="gdes">Graphic Design</option>
<option value="lit">Literature</option>
<option value="music">Music</option>
<hr>
<option value="aeroeng">Aerospace Engineering</option>
<option value="biochemeng">Biochemical Engineering</option>
<option value="civileng">Civil Engineering</option>
<option value="compeng">Computer Engineering</option>
<option value="eleng">Electrical Engineering</option>
<option value="mecheng">Mechanical Engineering</option>
</select>
效果如下:
圖片
其他特性
原生 CSS 嵌套
目前所有主流瀏覽器都支持原生 CSS 嵌套。使用 CSS 嵌套,可以編寫更少的代碼,并且代碼更易于閱讀和維護(hù)。
在沒(méi)有CSS嵌套時(shí),只能這樣輸入完整的選擇器路徑:
.parent1 .child1,
.parent2 .child1 {
color: red;
}
.parent1 .child2,
.parent2 .child2 {
color: green;
}
.parent1 .child2:hover,
.parent2 .child2:hover {
color: blue;
}
使用新的原生嵌套語(yǔ)法,可以將子選擇器嵌套在父選擇器中:
.parent1, .parent2 {
.child1 {
color: red;
}
.child2 {
color: green;
&:hover {
color: blue;
}
}
}
瀏覽器支持:
text-wrap:balance | pretty
在開發(fā)時(shí),我們無(wú)法預(yù)知文本的樣式和長(zhǎng)度。但瀏覽器內(nèi)置了文本換行的智能處理機(jī)制,如text-wrap:balance和text-wrap:pretty,它們能自動(dòng)優(yōu)化文本布局,確保文本塊的和諧和美觀,同時(shí)避免孤立字符和不當(dāng)?shù)倪B字符使用。這些功能無(wú)需手動(dòng)干預(yù),且適應(yīng)各種語(yǔ)言和文本內(nèi)容。
p {
text-wrap: balance;
}
瀏覽器支持:
light-dark()
light-dark() 函數(shù)能夠根據(jù)當(dāng)前顏色方案自動(dòng)選擇兩種顏色中的一種進(jìn)行輸出,從而實(shí)現(xiàn)顏色的自適應(yīng)顯示。該函數(shù)接受兩個(gè)顏色值作為其參數(shù)。根據(jù)正在使用的顏色方案,它將輸出第一個(gè)或第二個(gè)顏色參數(shù)。
light-dark(<color>, <color>);
根據(jù)規(guī)范,如果使用的顏色方案是light或未知,則該函數(shù)計(jì)算為第一種顏色的計(jì)算值;如果使用的顏色方案是dark,則計(jì)算為第二種顏色的計(jì)算值。
使用的顏色方案不僅是用戶選擇的亮暗模式,還需要根據(jù)color-scheme屬性的值確定使用的顏色方案。color-scheme屬性可以指示元素使用哪種顏色方案進(jìn)行渲染,這個(gè)方案會(huì)與用戶的偏好進(jìn)行協(xié)商,最終確定使用的顏色方案。因此,在使用light-dark()函數(shù)時(shí),還需要在CSS中包含對(duì)應(yīng)的color-scheme聲明,以確保函數(shù)能夠正確工作。
:root {
color-scheme: light dark;
}
:root {
--text-color: light-dark(#333, #ccc);
}
對(duì)于上面的代碼,在淺色模式下返回第一個(gè)值,在深色模式下返回第二個(gè)值。
注意:light-dark() 函數(shù)的設(shè)計(jì)初衷是為了提供一個(gè)簡(jiǎn)單的中間解決方案,僅支持亮色和暗色的切換,并僅適用于顏色值。
瀏覽器支持:
圖片
:has() 選擇器
在過(guò)去的 20 年里,開發(fā)者們一直期待在 CSS 中加入“父選擇器”。隨著在 Chrome 105 中引入:has()選擇器,這一愿望終于得以實(shí)現(xiàn)。
例如,可以使用.card:has(img.hero)選擇那些包含英雄圖像子元素的.card元素。
.card:has(.card__media) {
grid-template-areas:
"title"
"blurb"
"author"
"media";
padding-bottom: 0;
}
瀏覽器支持:
容器查詢
容器查詢可以根據(jù)元素的父元素或祖先元素的大小來(lái)設(shè)置元素的樣式。這與傳統(tǒng)的媒體查詢有所不同,媒體查詢是基于整個(gè)瀏覽器視口的大小來(lái)設(shè)置樣式的。
要想設(shè)置容器查詢,需要給被查詢的元素設(shè)置 container-type 屬性來(lái)指定容器的類型。語(yǔ)法如下:
container-type: inline-size;
例如:
.card-layout {
container-type: inline-size;
}
@container (min-width: 768px) {
.card {
display: grid;
font-size: 3rem;
color: blue;
}
}
這樣,當(dāng)容器 card-layout 的寬度大于 768px 時(shí),其子元素 card 就使用 grid 布局。
瀏覽器支持:
圖片