CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)終于正式支持了
在最新的Chrome 115中,令人無(wú)比期待的CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)(CSS scroll-driven animations)[1]終于正式支持了~有了它,幾乎以前任何需要JS監(jiān)聽(tīng)滾動(dòng)的交互都可以純 CSS 實(shí)現(xiàn)了,就是這么強(qiáng)大,一起了解一下吧!
溫馨提示:文章略長(zhǎng),建議收藏后反復(fù)查閱
一、快速入門(mén) CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)
直接介紹 API 可能不太感興趣,這里先通過(guò)一個(gè)最直觀的例子感受一下。
下面是一個(gè)頁(yè)面進(jìn)度指示器,進(jìn)度隨著頁(yè)面的滾動(dòng)而變化。
頁(yè)面很簡(jiǎn)單,很多內(nèi)容和一個(gè)進(jìn)度條。
<div class="progress"></div>
...很多內(nèi)容
進(jìn)度條是fixed定位。
.progress{
position: fixed;
top: 0;
left: 0;
right: 0;
height: 10px;
background-color: #F44336;
transform-origin: 0 50%;
}
然后給這個(gè)進(jìn)度條添加一個(gè)動(dòng)畫(huà),表示進(jìn)度從0到100%。
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
接著給這個(gè)進(jìn)度條綁定動(dòng)畫(huà)。
.progress{
animation: grow-progress 3s linear;
}
刷新頁(yè)面,可以看到進(jìn)度條在3s內(nèi)從0增長(zhǎng)到了100%。
顯然這種動(dòng)畫(huà)沒(méi)什么意義,我們需要在滾動(dòng)時(shí)才觸發(fā),并且滾動(dòng)多少,動(dòng)畫(huà)就播放多少。
注意:動(dòng)畫(huà)時(shí)長(zhǎng)不能為0,因?yàn)闉?表示動(dòng)畫(huà)不執(zhí)行,所以必須寫(xiě)上一個(gè)任意非零時(shí)間,或者直接為auto。
最后,加上「最核心」的一段,也就是今天的主角animation-timeline。
.progress{
/*...*/
animation-timeline: scroll();
}
這樣進(jìn)度條就乖乖的跟隨頁(yè)面滾動(dòng)而變化了(注意Chrome 115+)。
完整代碼可以訪(fǎng)問(wèn):
- CSS scroll-driven-animations (juejin.cn)[2]
- CSS scroll-driven-animations-back (codepen.io)[3]
是不是非常簡(jiǎn)單?是不是非常神奇?如果你感興趣,可以接著往下看。
二、CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)
大家可能知道,傳統(tǒng) JS 監(jiān)聽(tīng)滾動(dòng)有一些問(wèn)題,如下:
- 現(xiàn)代瀏覽器在單獨(dú)的進(jìn)程上執(zhí)行滾動(dòng),因此只能異步傳遞滾動(dòng)事件。
- 由于是異步傳遞,因此主線(xiàn)程動(dòng)畫(huà)容易出現(xiàn)卡頓
因此,為了解決滾動(dòng)卡頓的問(wèn)題,CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)應(yīng)運(yùn)而生。那么,什么是 CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)?
默認(rèn)情況下,動(dòng)畫(huà)是「隨著時(shí)間的流逝」而播放的。
「CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)」指的是將「動(dòng)畫(huà)的執(zhí)行過(guò)程由頁(yè)面滾動(dòng)」進(jìn)行接管,也就是這種情況下,「動(dòng)畫(huà)只會(huì)跟隨頁(yè)面滾動(dòng)的變化而變化」,也就是滾動(dòng)多少,動(dòng)畫(huà)就執(zhí)行多少,「時(shí)間不再起作用」。
如何改變動(dòng)畫(huà)的時(shí)間線(xiàn)呢?那就需要用到這個(gè)核心概念了:animation-timeline[4],表示「動(dòng)畫(huà)時(shí)間線(xiàn)」(或者叫時(shí)間軸),用于控制 CSS 動(dòng)畫(huà)進(jìn)度的時(shí)間線(xiàn),是必不可少的一個(gè)屬性。
默認(rèn)值是auto,也是就傳統(tǒng)的時(shí)間線(xiàn)。下面是它一些關(guān)鍵詞。
/* 關(guān)鍵詞 */
animation-timeline: none;
animation-timeline: auto;
/* 命名時(shí)間線(xiàn) */
animation-timeline: --timeline_name;
/* 滾動(dòng)時(shí)間線(xiàn) */
animation-timeline: scroll();
animation-timeline: scroll(scroller axis);
/* 視圖時(shí)間線(xiàn) */
animation-timeline: view();
animation-timeline: view(axis inset);
是不是有點(diǎn)混亂?不要慌,實(shí)際滾動(dòng)場(chǎng)景千千萬(wàn),這里可以分為兩大類(lèi):一類(lèi)是「滾動(dòng)進(jìn)度時(shí)間線(xiàn)」,也就是上面的關(guān)鍵詞scroll(),還有一類(lèi)是「視圖進(jìn)度時(shí)間線(xiàn)」,也就是關(guān)鍵詞view()。
兩者形式對(duì)應(yīng)兩種不同的應(yīng)用場(chǎng)景,這是什么意思呢?下面一一介紹。
三. CSS 滾動(dòng)進(jìn)度時(shí)間線(xiàn)
「滾動(dòng)進(jìn)度時(shí)間線(xiàn)(scroll progress timeline)」。表示頁(yè)面或者容器滾動(dòng),「將滾動(dòng)進(jìn)度映射到動(dòng)畫(huà)進(jìn)度上」。起始滾動(dòng)位置代表 0% 進(jìn)度,結(jié)束滾動(dòng)位置代表 100% 進(jìn)度,下面是一個(gè)可視化演示
https://scroll-driven-animations.style/tools/scroll-timeline/progress/。
在上面的進(jìn)度條例子中,我們用到的就是scroll progress timeline,因?yàn)槲覀儽O(jiān)聽(tīng)的就是頁(yè)面的滾動(dòng)。
animation-timeline: scroll();
這里的scroll()是一個(gè)簡(jiǎn)寫(xiě),可以傳遞兩個(gè)參數(shù),分別是<scroller>和<axis>。
<scroller>表示滾動(dòng)容器,支持以下幾個(gè)關(guān)鍵值
- nearest:使用最近的祖先滾動(dòng)容器*(默認(rèn))*
- root:使用文檔視口作為滾動(dòng)容器。
- self:使用元素本身作為滾動(dòng)容器。
<axios>表示滾動(dòng)方向,支持以下幾個(gè)關(guān)鍵值
- block:滾動(dòng)容器的塊級(jí)軸方向*(默認(rèn))*。
- inline:滾動(dòng)容器內(nèi)聯(lián)軸方向。
- y:滾動(dòng)容器沿 y 軸方向。
- x:滾動(dòng)容器沿 x 軸方向。
/* 無(wú)參數(shù) */
animation-timeline: scroll();
/* 設(shè)置滾動(dòng)容器 */
animation-timeline: scroll(nearest); /* 默認(rèn) */
animation-timeline: scroll(root);
animation-timeline: scroll(self);
/* 設(shè)置滾動(dòng)方向 */
animation-timeline: scroll(block); /* 默認(rèn) */
animation-timeline: scroll(inline);
animation-timeline: scroll(y);
animation-timeline: scroll(x);
/* 同時(shí)設(shè)置 */
animation-timeline: scroll(block nearest); /* 默認(rèn) */
animation-timeline: scroll(inline root);
animation-timeline: scroll(x self);
需要注意的是,這里語(yǔ)法容錯(cuò)性比較強(qiáng),沒(méi)有順序要求,會(huì)自動(dòng)識(shí)別。
因此,如果需要監(jiān)聽(tīng)橫向滾動(dòng),可以這樣。
animation-timeline: scroll(inline);
不知大家發(fā)現(xiàn)沒(méi),前面的滾動(dòng)容器只有三個(gè)關(guān)鍵詞,并不能通過(guò)#id方式任意指定滾動(dòng)容器,真的能滿(mǎn)足所有需求嗎?
當(dāng)然不行!有時(shí)候結(jié)構(gòu)稍微復(fù)雜一點(diǎn),自動(dòng)查找就不適用了,并且這里的「最近祖先滾動(dòng)容器還受到絕對(duì)定位的影響」,因此,我們還需要手動(dòng)去指定滾動(dòng)容器。
官方的解決方式是「創(chuàng)建一個(gè)帶有名稱(chēng)的時(shí)間線(xiàn)」,具體做法是,在「滾動(dòng)容器」上添加一個(gè)屬性scroll-timeline-name[5],這個(gè)屬性值必須以--開(kāi)頭,就像 CSS 變量一樣,還可以通過(guò)scroll-timeline-axis[6]設(shè)置滾動(dòng)方向,此時(shí)的animation-timeline就不用默認(rèn)的scroll()了,而是改用前面設(shè)置的變量,示意如下:
@keyframes animate-it { … }
/*滾動(dòng)容器*/
.scroller {
scroll-timeline-name: --my-scroller;
scroll-timeline-axis: inline;
}
.scroller .subject {
animation: animate-it linear;
animation-timeline: --my-scroller;
}
這里的scroll-timeline-axis和scroll-timeline-name還可以簡(jiǎn)寫(xiě)成一個(gè)屬性scroll-timeline。
scroll-timeline-name: --my-scroller;
scroll-timeline-axis: inline;
/**可簡(jiǎn)寫(xiě)為**/
scroll-timeline: --my-scroller inline;
下面來(lái)看一個(gè)橫向滾動(dòng)的例子,剛好可以把上面的幾個(gè)新概念都用上。
布局還是類(lèi)似,只是放在了一個(gè)可以橫向滾動(dòng)的容器中。
<main>
<div class="progress"></div>
...很多內(nèi)容...
</main>
給main設(shè)置橫向滾動(dòng),.progress設(shè)置fixed定位,還有動(dòng)畫(huà)和上個(gè)例子一樣。
main{
display: flex;
overflow: scroll;
}
.progress{
position: fixed;
top: 0;
left: 0;
right: 0;
height: 10px;
background-color: #F44336;
transform-origin: 0 50%;
animation:grow-progress 3s linear;
}
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
由于這里main才是滾動(dòng)容器,并不是頁(yè)面,而.progress是fixed定位,如果直接用scroll(nearest)獲取到的就是頁(yè)面根容器,并不是main,所以這里需要用命名scroll-timeline,實(shí)現(xiàn)如下:
main{
/**/
scroll-timeline: --scrollcontainer inline;
}
.progress{
/**/
animation-timeline: --scrollcontainer;
}
這樣就可以將橫向滾動(dòng)進(jìn)度一一映射到動(dòng)畫(huà)上了,而且不受結(jié)構(gòu)限制,非常自由。
完整代碼可以查看:
- CSS scroll-driven-animations-inline (juejin.cn)[7]
- CSS scroll-driven-animations-inline (codepen.io)[8]
四、CSS 視圖進(jìn)度時(shí)間線(xiàn)
「視圖進(jìn)度時(shí)間線(xiàn)(view progress timeline)」。這個(gè)名字有些難以理解,其實(shí)表示的是一個(gè)元素出現(xiàn)在頁(yè)面視野范圍內(nèi)的進(jìn)度,也就是關(guān)注的是元素自身位置。元素剛剛出現(xiàn)之前代表 0%進(jìn)度,元素完全離開(kāi)之后代表 100% 進(jìn)度,下面是一個(gè)可視化演示:
https://scroll-driven-animations.style/tools/view-timeline/progress/。
這個(gè)概念非常像JS中的Intersection_Observer_API[9],也就「交叉觀察者」,可以「監(jiān)測(cè)到元素在可視區(qū)」的情況,因此,在這種場(chǎng)景中,無(wú)需關(guān)注滾動(dòng)容器是哪個(gè),只用處理自身就行了。
和前面的scroll progress time語(yǔ)法類(lèi)似,也有一個(gè)快捷語(yǔ)法。
animation-timeline: view()
由于無(wú)需關(guān)注滾動(dòng)容器,所以它的參數(shù)也不一樣,分別是<axios>和<inset>。
<axios>表示滾動(dòng)方向,支持以下幾個(gè)關(guān)鍵值
- block:滾動(dòng)容器的塊級(jí)軸方向*(默認(rèn))*。
- inline:滾動(dòng)容器內(nèi)聯(lián)軸方向。
- y:滾動(dòng)容器沿 y 軸方向。
- x:滾動(dòng)容器沿 x 軸方向。
<inset>表示調(diào)整元素的視區(qū)范圍,有點(diǎn)類(lèi)似scroll-padding,支持兩個(gè)值,表示開(kāi)始和結(jié)束兩個(gè)范圍。
animation-timeline: view(auto); /* 默認(rèn)值 */
animation-timeline: view(20%);
animation-timeline: view(200px);
animation-timeline: view(20% 40%);
animation-timeline: view(20% 200px);
animation-timeline: view(100px 200px);
animation-timeline: view(auto 200px);
這里的<inset>還可以用view-timeline-inset[10]單獨(dú)來(lái)表示,不過(guò)需要注意的是,這種用法要使用命名的view progress time,如下:
scroll-timeline: --my-scroller block;
view-timeline-inset: 20% 200px;
animation-timeline: --my-scroller;
按照我的經(jīng)驗(yàn),view progress time中使用命名的情況比較少,因?yàn)闊o(wú)需知道滾動(dòng)容器,因此推薦用view()。
下面來(lái)看一個(gè)例子,有一個(gè)列表。
<div>歡</div>
<div>迎</div>
<div>關(guān)</div>
<div>注</div>
<div>前</div>
<div>端</div>
<div>偵</div>
...
簡(jiǎn)單修飾后,效果如下:
現(xiàn)在,我們添加一個(gè)淡入和縮放的動(dòng)畫(huà)。
@keyframes appear {
from {
opacity: 0;
transform: scaleX(0);
}
to {
opacity: 1;
transform: scaleX(1);
}
}
然后,通過(guò)animation-time綁定在每個(gè)元素上,因?yàn)槲覀兿胱鲆粋€(gè)元素進(jìn)入的動(dòng)畫(huà),所以要用到view progress timeline。
div{
/**/
animation: appear 1s linear both;
animation-timeline: view();
}
可以得到這樣的效果:
效果是出來(lái)了,不過(guò)好像有點(diǎn)太過(guò)了,太夸張了,可以看到,「每個(gè)元素在滾動(dòng)出現(xiàn)到離開(kāi)的過(guò)程中都完整的執(zhí)行了我們定義的動(dòng)畫(huà)」。那么,有沒(méi)有辦法讓這個(gè)范圍變小一點(diǎn)呢?默認(rèn)的范圍如下:
當(dāng)然也是可以的,這里就需要用到view的第二個(gè)參數(shù)<inset>了,比如設(shè)置40% 0表示調(diào)整視區(qū)范圍,相當(dāng)于將滾動(dòng)容器上邊距減少了 40%,當(dāng)滾動(dòng)到視區(qū)上面40%的時(shí)候就完成了動(dòng)畫(huà)(默認(rèn)是滾動(dòng)到0%,也就是完全離開(kāi)的時(shí)候)。
div{
/**/
animation-timeline: view(40% 0);
}
還可以更加激進(jìn)一點(diǎn),設(shè)置成100%,相當(dāng)于元素一旦完全進(jìn)入,動(dòng)畫(huà)就執(zhí)行完成了,這樣元素出現(xiàn)動(dòng)畫(huà)會(huì)更加和諧。
div{
/**/
animation-timeline: view(100% 0);
}
此時(shí)的動(dòng)畫(huà)范圍就更小了,如下:
效果如下,是不是感覺(jué)沒(méi)那么夸張了呢?
完整代碼可以查看:
- CSS scroll-driven-animations-view (juejin.cn)[11]
- CSS scroll-driven-animations-view (codepen.io)[12]
五、CSS 動(dòng)畫(huà)范圍區(qū)間
默認(rèn)情況下,動(dòng)畫(huà)會(huì)根據(jù)滾動(dòng)區(qū)間范圍一一映射,就比如第一個(gè)滾動(dòng)指示器的例子,滾動(dòng)多少,指示器的進(jìn)度就走多少。
但有時(shí)候,我們并不需要完整的區(qū)間,比如這個(gè)例子,右下角的返回頂部按鈕。
像這種情況下,我們其實(shí)「只需要前面滾動(dòng)一定距離」就可以讓返回按鈕完全出現(xiàn)了,對(duì)應(yīng)關(guān)系應(yīng)該是這樣。
那么,如何截取一定的滾動(dòng)區(qū)間呢?這就要涉及一個(gè)新的屬性,叫做animation-range[13],也就是“動(dòng)畫(huà)范圍”。
這里也要分兩種場(chǎng)景,也就是前面提到的「滾動(dòng)進(jìn)度時(shí)間線(xiàn)」和「視圖進(jìn)度時(shí)間線(xiàn)」。
1、滾動(dòng)進(jìn)度時(shí)間線(xiàn)
首先來(lái)看scroll()場(chǎng)景,由于只是滾動(dòng)容器的監(jiān)聽(tīng),因此比較簡(jiǎn)單,直接設(shè)置范圍就行了。
animation-range: normal; /* 等價(jià)于 normal normal */
animation-range: 20%; /* 等價(jià)于 20% normal */
animation-range: 100px; /* 等價(jià)于 100px normal */
比如上面這個(gè)返回頂部的例子,動(dòng)畫(huà)其實(shí)很簡(jiǎn)單,就是一個(gè)向上的位移動(dòng)畫(huà)。
@keyframes back-progress {
from { transform: translateY(150%); }
to { transform: translateY(0%); }
}
如果僅僅添加一個(gè)滾動(dòng)時(shí)間軸。
.back{
/**/
animation: back-progress 1s linear forwards;
animation-timeline: scroll();
}
那么,這個(gè)返回按鈕就像滾動(dòng)進(jìn)度條那樣,慢慢的出來(lái),直到滾動(dòng)到最底部才完全出來(lái),效果如下:
這時(shí)只需要在[0, 固定距離]的范圍內(nèi)出現(xiàn)就好了,表示只在這個(gè)區(qū)間范圍內(nèi)觸發(fā)動(dòng)畫(huà),關(guān)鍵代碼如下:
.back{
/**/
animation: back-progress 1s linear forwards;
animation-timeline: scroll();
animation-range: 0 100px;
}
這樣就實(shí)現(xiàn)了滾動(dòng)100px時(shí)自動(dòng)出現(xiàn)的返回頂部按鈕,100px后按鈕會(huì)一直顯示。
完整代碼可以查看:
- CSS scroll-driven-animations-back (juejin.cn)[14]
- CSS scroll-driven-animations-back (codepen.io)[15]
還有一個(gè)頭部吸頂?shù)睦?,原理也是?lèi)似的,如下:
頭部是一個(gè)高度和字號(hào)不斷變小的動(dòng)畫(huà),然后需要設(shè)置一下animation-range,關(guān)鍵實(shí)現(xiàn)如下:
@keyframes header {
to {
height: 60px;
font-size: 30px;
}
}
.header{
/**/
animation: header 1s linear forwards;
animation-timeline: scroll();
animation-range: 0 calc(100vh - 60px);
}
完整代碼可以查看:
- CSS scroll-driven-animations-header (juejin.cn)[16]
- CSS scroll-driven-animations-header (codepen.io)[17]
2、視圖進(jìn)度時(shí)間線(xiàn)
再來(lái)看看view()場(chǎng)景。由于涉及到元素和可視區(qū)域的交叉,情況稍微復(fù)雜一些,如下:
animation-range: cover; /* 等價(jià)于 cover 0% cover 100% */
animation-range: contain; /* 等價(jià)于 contain 0% contain 100% */
animation-range: cover 20%; /* 等價(jià)于 cover 20% cover 100% */
animation-range: contain 100px; /* 等價(jià)于 contain 100px cover 100% */
animation-range: normal 25%;
animation-range: 25% normal;
animation-range: 25% 50%;
animation-range: entry exit; /* 等價(jià)于 entry 0% exit 100% */
animation-range: cover cover 200px; /* 等價(jià)于 cover 0% cover 200px */
animation-range: entry 10% exit; /* 等價(jià)于 entry 10% exit 100% */
animation-range: 10% exit 90%;
animation-range: entry 10% 90%;
有以下關(guān)鍵詞
- 「cover」:元素首次開(kāi)始進(jìn)入滾動(dòng)容器可見(jiàn)范圍(0%)到完全離開(kāi)的過(guò)程(100% ),也就是元素只需要和可視范圍有交集(默認(rèn))。
- 「contain」:元素完全進(jìn)入滾動(dòng)容器可見(jiàn)范圍(0%)到剛好要離開(kāi)的過(guò)程(100% ),也就是元素必須完全在可見(jiàn)范圍才會(huì)觸發(fā)。
- 「entry」:元素進(jìn)入滾動(dòng)容器可見(jiàn)范圍的過(guò)程,剛進(jìn)入是 0%,完全進(jìn)入是 100%。
- 「exit」:元素離開(kāi)滾動(dòng)容器可見(jiàn)范圍的過(guò)程,剛離開(kāi)是 0%,完全離開(kāi)是 100%。
- 「entry-crossing」:和「entry」比較類(lèi)似,暫時(shí)沒(méi)有發(fā)現(xiàn)明顯差異。
- 「exit-crossing」:和「exit」比較類(lèi)似,暫時(shí)沒(méi)有發(fā)現(xiàn)明顯差異。
下面做了一個(gè)示意圖,表示各自的范圍區(qū)間。
如果還是不太清楚,可以用下面這個(gè)工具去對(duì)比各自的差異。
https://scroll-driven-animations.style/tools/view-timeline/progress。
比如前面的列表進(jìn)入時(shí)的動(dòng)畫(huà),之前是用view(100% 0)實(shí)現(xiàn)的,大家有沒(méi)有發(fā)現(xiàn),這個(gè)效果其實(shí)和entry的示意效果一樣的?
如果用animation-range就很好理解了,這里需要進(jìn)入動(dòng)畫(huà),所以可以直接用entry。
div{
animation: appear 1s linear forwords;
animation-timeline: view();
animation-range: entry; /*只在進(jìn)入過(guò)程中生效*/
}
同樣可以實(shí)現(xiàn)相同的效果。
除此之外還可以同時(shí)設(shè)置進(jìn)入和離開(kāi)兩種動(dòng)畫(huà),這就需要定義兩個(gè)動(dòng)畫(huà),然后分別給兩個(gè)動(dòng)畫(huà)定義動(dòng)畫(huà)區(qū)間,關(guān)鍵實(shí)現(xiàn)如下:
div{
animation: appear 1s linear forwards,
disappear 1s linear forwards;
animation-timeline: view();
animation-range: entry,exit; /*進(jìn)入過(guò)程執(zhí)行appear,離開(kāi)過(guò)程執(zhí)行disappear*/
}
/*出現(xiàn)動(dòng)畫(huà)*/
@keyframes appear {
0% {
opacity: 0;
transform: scaleX(0);
}
100% {
opacity: 1;
transform: scaleX(1);
}
}
/*離開(kāi)*/
@keyframes disappear {
100% {
opacity: 0;
transform: scaleX(0);
}
0% {
opacity: 1;
transform: scaleX(1);
}
}
這樣就得到一個(gè)進(jìn)入和離開(kāi)均存在動(dòng)畫(huà)的滾動(dòng)列表。
完整代碼可以查看:
- CSS scroll-driven-animations-range (juejin.cn)[18]
- CSS scroll-driven-animations-range (codepen.io)
另外,還可以將animation-range合并到同一個(gè)動(dòng)畫(huà)中,在關(guān)鍵幀前面加上entry這些關(guān)鍵詞,這樣就無(wú)需指定animation-range中了,示意代碼如下:
div{
animation: animate-in-and-out 1s linear forwards;
animation-timeline: view();
}
@keyframes animate-in-and-out {
entry 0% {
opacity: 0;
transform: scaleX(0);
}
entry 100% {
opacity: 1;
transform: scaleX(1);
}
exit 100% {
opacity: 0;
transform: scaleX(0);
}
exit 0% {
opacity: 1;
transform: scaleX(1);
}
}
六、更多有趣的案例
除了以上一些案例外,CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)還能做更多有趣的事情,這里推薦一個(gè)網(wǎng)站。
比如這個(gè) Cover Flow 效果:
參見(jiàn):https://scroll-driven-animations.style/demos/cover-flow/css/。
還有下面的卡片堆疊效果:
參見(jiàn):https://scroll-driven-animations.style/demos/stacking-cards/css/。
還有其他的例子就不展示了,大家可以自行體驗(yàn)。
七、用一張圖總結(jié)一下
總的來(lái)說(shuō),CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)為以后的交互帶來(lái)了無(wú)限可能,下面用一張圖總結(jié)一下。
參考資料:
[1]CSS_scroll-driven_animations: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll-driven_animations。
[2]CSS scroll-driven-animations (juejin.cn): https://code.juejin.cn/pen/7258614059845566521。
[3]CSS scroll-driven-animations-back (codepen.io): https://codepen.io/xboxyan/pen/abQjwLa。
[4]animation-timeline: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline。
[5]scroll-timeline-name: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-timeline-name。
[6]scroll-timeline-axis: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-timeline-axis。
[7]CSS scroll-driven-animations-inline (juejin.cn): https://code.juejin.cn/pen/7258615967712804925。
[8]CSS scroll-driven-animations-inline (codepen.io): https://codepen.io/xboxyan/pen/dyQjRQx。
[9]Intersection_Observer_API: https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API。
[10]view-timeline-inset: https://developer.mozilla.org/en-US/docs/Web/CSS/view-timeline-inset。
[11]CSS scroll-driven-animations-view (juejin.cn): https://code.juejin.cn/pen/7258616829306732604。
[12]CSS scroll-driven-animations-view (codepen.io): https://codepen.io/xboxyan/pen/WNYKOPO。
[13]animation-range: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-range。
[14]CSS scroll-driven-animations-back (juejin.cn): https://code.juejin.cn/pen/7258613645440417849。
[15]CSS scroll-driven-animations-back (codepen.io): https://codepen.io/xboxyan/pen/PoxBjVz。
[16]CSS scroll-driven-animations-header (juejin.cn): https://code.juejin.cn/pen/7258894357275607077。
[17]CSS scroll-driven-animations-header (codepen.io): https://codepen.io/xboxyan/pen/qBQyYjE。
[18]CSS scroll-driven-animations-range (juejin.cn): https://code.juejin.cn/pen/7258632665178308666。