添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
留胡子的消炎药  ·  Advanced Pexip web ...·  2 天前    · 
痛苦的双杠  ·  先理解Mask ...·  2 年前    · 
果断的土豆  ·  spring boot ...·  2 年前    · 
神勇威武的山羊  ·  mdiapipe pose姿态 ...·  2 年前    · 

CSS 動畫進度控制 animation-timeline、view-timeline、animation-range

雖然實作 CSS 動畫通常都需要手動設定「進度百分比」,但目前已有部分瀏覽器支援「視窗可視位置」以及「瀏覽器卷軸」控制動畫進度的功能,這篇教學會介紹運用 CSS 的 animation-timeline、view-timeline 和 animation-range 樣式屬性,實現進階的動畫進度控制功能。

  • 注意,目前 部分瀏覽器不支援 這些樣式屬性 ( Firefox、Safari、IE )!
  • 建議先閱讀: CSS 動畫 animation
  • 快速導覽:

  • animation-timeline 動畫進度控制 ( 動畫時間軸 )
    • animation-timeline: view() 畫面高度
    • animation-timeline: scroll() 捲軸位置
    • view-timeline 可視範圍時間軸
    • animation-range 動畫執行範圍
    • animation-timeline 動畫進度控制 ( 動畫時間軸 )

      animation-timeline 是一個可以「 根據畫面或卷軸控制動畫進度 」的樣式屬性,會 將元素在「可視範圍」裡的位置,或元素所在階層的「視窗捲軸」,當作「時間軸 timeline」,時間軸對應到動畫所設定的進度百分比,就夠單純透過 CSS 讀取這些元素之外數值,在不需要 JavaScript 的輔助下,控制動畫進度 ,這個樣式沒有繼承特性,具有下列屬性值:

      注意, animation-timeline 在 CSS 中的順序必須擺在 animation-name 之後。

      下方的範例會展示使用 view() 屬性值,搭配各種不同參數所呈現的效果,當使用者捲動捲軸時,會看見內容方塊出現變色、尺寸改變的效果, 可以注意設定了 start end 的元素,會在指定的位置才發生改變,位置外的樣貌會呈現原本元素的樣式屬性

      線上展示: https://codepen.io/oxxo/pen/azbvVrv

      <!-- HTML 程式碼 -->
      垂直方向改變動畫進度
      <div class="out a">
        <div>往下拉,觀察變化狀況</div><div class="in"></div><div></div>
      垂直方向改變動畫進度 ( 限制上 50px 下 100px )
      <div class="out b">
        <div>往下拉,觀察變化狀況</div><div class="in"></div><div></div>
      水平方向改變動畫進度
      <div class="out c">
        <div>往右拉,觀察變化狀況</div><div class="in"></div><div></div>
      水平方向改變動畫進度 ( 限制左 50px 右 100px )
      <div class="out d">
        <div>往右拉,觀察變化狀況</div><div class="in"></div><div></div>
      <!-- CSS 程式碼 -->
      <style>
        .out {
          width: 300px;
          height: 200px;
          overflow: scroll;      /* 隱藏超出範圍的子元素並出現捲軸 */
          margin: 5px 0 20px 0 ;
          border: 1px solid #000;
        /* 使用一般的 div 撐高畫面,並用漸層背景讓效果更明顯 */
        div:not([class]) {
          width: 400px;
          height: 300px;
          background: repeating-linear-gradient(45deg,#fff 0%,  #fff 5%,#eee 5%, #eee 10%);
        /* 水平捲動的一般 div 高度較小,讓變化的 div 一開始就出現 */
        .c div:not([class]), .d div:not([class]) {height: 100px;}
        /* 動畫進度會改變的 div,注意只使用了動畫名稱而已 */
        .in {
          width: 100px;
          height: 100px;
          background: red;
          animation-name: oxxo; /* 只使用動畫名稱 */
        /* 動畫設定 */
        @keyframes oxxo {
          0% {background: red;}
          25% {background: yellow;}
          50% {background: green;}
          75% {background: blue;}
          100% {
            background: black;
            width: 20px;
            height: 20px;
        .a .in {animation-timeline: view();}            /* 元素在顯示畫面中垂直方向的位置,等同 view(0% 0%) */
        .b .in {animation-timeline: view(50px 100px);}  /* 元素在顯示畫面中垂直方向的位置 */
        .c .in {
          margin: 0 300px;                              /* 讓畫面出現水平捲軸 */
          animation-timeline: view(inline);             /* 元素在顯示畫面中水平方向的位置,等同 view(inline 0% 0%) */
        .d .in {
          margin: 0 300px;                               /* 讓畫面出現水平捲軸 */
          animation-timeline: view(inline 50px 100px );  /* 元素在顯示畫面中水平方向的位置 */
      </style>
      

      下方的範例會展示使用 scroll() 屬性值,搭配各種不同參數所呈現的效果,第一組元素會在捲動最靠近元素的父層元素捲軸時發生變化,第二組則是會在捲動頁面捲軸時發生變化,第三組會在捲動元素本身捲軸時發生變化。

      線上展示:https://codepen.io/oxxo/pen/gbOaXJo

      <!-- HTML 程式碼 -->
      最靠近元素的父層元素捲軸
      <div class="out a">
        <div>往下拉,觀察變化狀況</div>
        <div class="in">apple<br>banana<br>oxxo<br>coconut<br>papaya</div>
        <div></div>
      網頁文件捲軸
      <div class="out b">
        <div>往下拉,觀察變化狀況</div>
        <div class="in">apple<br>banana<br>oxxo<br>coconut<br>papaya</div>
        <div></div>
      元素本身捲軸
      <div class="out c">
        <div>往右拉,觀察變化狀況</div>
        <div class="in">apple<br>banana<br>oxxo<br>coconut<br>papaya</div>
        <div></div>
      <br><br><br><br><br><br><br><br><br><br><br><br>
      <!-- CSS 程式碼 -->
      <style>
        .out {
          width: 300px;
          height: 150px;
          overflow: scroll;      /* 隱藏超出範圍的子元素並出現捲軸 */
          margin: 5px 0 20px 0 ;
          border: 1px solid #000;
        /* 使用一般的 div 撐高畫面,並用漸層背景讓效果更明顯 */
        div:not([class]) {
          background: repeating-linear-gradient(45deg,#fff 0%,  #fff 5%,#eee 5%, #eee 10%);
          width: 400px;
          height: 50px;
        /* 撐高產生捲軸 */
        div:nth-child(3){height: 150px;}
        /* 動畫進度會改變的 div,注意只使用了動畫名稱而已 */
        .in {
          width: 100px;
          height: 100px;
          animation-name: oxxo; /* 動畫名稱 */
          overflow: scroll;     /* 元素本身產生捲軸 */
        /* 動畫設定 */
        @keyframes oxxo {
          0% {background: red;}
          25% {background: yellow;}
          50% {background: green;}
          75% {background: blue;}
          100% {
            background: black;
            width: 20px;
            height: 20px;
        .a .in {animation-timeline: scroll();}     /* 捲動最靠近元素的父層元素捲軸 */
        .b .in {animation-timeline: scroll(root);} /* 捲動頁面捲軸 */
        .c .in {animation-timeline: scroll(self);} /* 捲動元素本身捲軸 */
      </style>
      

      view-timeline 可視範圍時間軸

      view-timeline 是針對 animation-timeline 屬性值為 view() 的延伸樣式屬性,可以設定一組類似 CSS 變數的名稱與數值,接著只要呼叫這個名稱,就能執行和 view() 完全相同的效果,這個樣式是 view-timeline-nameview-timeline-axisview-inset 的縮寫格式,這些樣式屬性都沒有繼承特性,通常只使用 view-timeline 或單純透過 view() 來實現效果

      下方範例會將 animation-timeline: view() 的寫法換成 view-timeline,會呈現完全相同的效果,當元素離底部 100px 時就會開始變色變小,值到離頂部 50px 為止。

      線上展示:https://codepen.io/oxxo/pen/WbNQXBa

      <!-- HTML 程式碼 -->
      animation-timeline: view(50px 100px);
      <div class="out a">
        <div>往下拉,觀察變化狀況</div><div class="in"></div><div></div>
      view-timeline: --a 50px 100px;<br>
      animation-timeline: --a;
      <div class="out b">
        <div>往下拉,觀察變化狀況</div><div class="in"></div><div></div>
      <!-- CSS 程式碼 -->
      <style>
        .out {
          width: 300px;
          height: 200px;
          overflow: scroll;      /* 隱藏超出範圍的子元素並出現捲軸 */
          margin: 5px 0 20px 0 ;
          border: 1px solid #000;
        /* 使用一般的 div 撐高畫面,並用漸層背景讓效果更明顯 */
        div:not([class]) {
          width: 400px;
          height: 300px;
          background: repeating-linear-gradient(45deg,#fff 0%,  #fff 5%,#eee 5%, #eee 10%);
        /* 動畫進度會改變的 div,注意只使用了動畫名稱而已 */
        .in {
          width: 100px;
          height: 100px;
          background: red;
          animation-name: oxxo; /* 只使用動畫名稱 */
        /* 動畫設定 */
        @keyframes oxxo {
          0% {background: red;}
          100% {
            background: black;
            width: 20px;
            height: 20px;
        .a .in {
          view-timeline: --a 50px 100px;  /* 建立名稱和數值 */
          animation-timeline: --a;        /* 讀取名稱 */
        .b .in {animation-timeline: view(50px 100px);}
      </style>
      

      animation-range 動畫執行範圍

      animation-range 表示「動畫執行範圍」的樣式屬性,可以針對 view()scroll() 進行數值範圍設定,這個樣式是 animation-range-startanimation-range-end 的縮寫格式,這些樣式屬性都沒有繼承特性,通常只使用 animation-range 來實現效果。

      特別注意 animation-range 使用的數值和 view()scroll() 不同,animation-range 的數值表示「元素頂部距離出現位置的距離」

      下方會使用 animation-range 代替 view() 的設定,做出更容易理解位置的效果,和下方的另外一組對照組,呈現完全相同的效果。

      線上展示:https://codepen.io/oxxo/pen/zxYvPVG

      <!-- HTML 程式碼 -->
      animation-timeline: view();<br>
      animation-range: 50px 150px;
      <div class="out a">
        <div>往下拉,觀察變化狀況</div><div class="in"></div><div></div>
      animation-timeline: view(50px 50px);
      <div class="out b">
        <div>往下拉,觀察變化狀況</div><div class="in"></div><div></div>
      <!-- CSS 程式碼 -->
      <style>
        .out {
          width: 300px;
          height: 200px;
          overflow: scroll;      /* 隱藏超出範圍的子元素並出現捲軸 */
          margin: 5px 0 20px 0 ;
          border: 1px solid #000;
        /* 使用一般的 div 撐高畫面,並用漸層背景讓效果更明顯 */
        div:not([class]) {
          width: 400px;
          height: 300px;
          background: repeating-linear-gradient(45deg,#fff 0%,  #fff 5%,#eee 5%, #eee 10%);
        /* 動畫進度會改變的 div,注意只使用了動畫名稱而已 */
        .in {
          width: 100px;
          height: 100px;
          background: red;
          animation-name: oxxo; /* 只使用動畫名稱 */
        /* 動畫設定 */
        @keyframes oxxo {
          0% {background: red;}
          100% {
            background: black;
            width: 20px;
            height: 20px;
        .a .in {
          animation-timeline: view();   /* 使用可視範圍控制動畫進度 */
          animation-range: 50px 150px;  /* 元素頂部為 50px 開始動畫,值到距離 150px 為止 */
        .b .in {
          animation-timeline: view(50px 50px); /* 出現時 50px,結束值為 300px-250px */
      </style>
      

      對於 view() 而言,animation-range 也可以將上述的數值,搭配下方的屬性值,實現更進階的設定。

      normal 預設值,按照上述數值控制元素動畫進度。 contain 元素完全被包含在可視範圍中。 cover 元素在可視範圍進入到完全退出的過程。 元素開始退出可視範圍。 exit-crossing 元素開始穿越可視範圍結束邊緣 ( 類似 exit )。 entry 元素開始進入可視範圍。 entry-crossing 元素開始穿越可視範圍起始邊緣 ( 類似 entry )。

      下方會使用六個 div,從左到右分別是使用 containcoverexitexit-crossingentryentry-crossing 所呈現的效果,拖拉捲軸後,可以觀察元素進入和離開可視範圍時動畫進度的表現。

      線上展示:https://codepen.io/oxxo/pen/VYwvrJb

      <!-- HTML 程式碼 -->
      <div class="out">
        <div></div>
        <div class="in a"></div>
        <div class="in b"></div>
        <div class="in c"></div>
        <div class="in d"></div>
        <div class="in e"></div>
        <div class="in f"></div>
        <div></div>
      <!-- CSS 程式碼 -->
      <style>
        .out {
          width: 350px;
          height:250px;
          overflow: scroll;      /* 隱藏超出範圍的子元素並出現捲軸 */
          margin: 5px 0 20px 0 ;
          padding: 20px;
          border: 1px solid #000;  
          background: repeating-linear-gradient(45deg,#fff 0,  #fff 25px,#eee 25px, #eee 50px);
          background-attachment: local;
        /* 使用一般的 div 撐高畫面,並用漸層背景讓效果更明顯 */
        div:not([class]) {
          width: 400px;
          height: 300px;
          clear: both;
        /* 動畫進度會改變的 div,注意只使用了動畫名稱而已 */
        .in {
          width: 40px;
          height: 100px;
          margin: 5px;
          float: left;
          background: red;
          animation-name: oxxo;            /* 動畫名稱 */
          animation-fill-mode: forwards;   /* 動畫結束後停留在最後一格 */
          animation-timeline: view();      /* 使用可視範圍控制動畫進度 */
        /* 動畫設定 */
        @keyframes oxxo {
          0% {background: red;}
          100% {
            background: black;
            height: 200px;
        .a {animation-range: contain;}
        .b {animation-range: cover;}
        .c {animation-range: exit;}
        .d {animation-range: exit-crossing;}
        .e {animation-range: entry;}
        .f {animation-range: entry-crossing;}
      </style>
      

      因為 animation-scroll 無法讀取捲軸移動距離,而透過 animation-range 就能讀取捲軸捲動的數值,透過下拉捲軸的距離控制動畫進度,下方範例會將三個 div 套用不同的 animation-range,執行後將捲軸向下拉動,可以發現三個 div 會在不同高度捲軸時開始執行動畫進度,產生有趣的視覺效果。

      線上展示:https://codepen.io/oxxo/pen/jEObajd

      <!-- HTML 程式碼 -->
      <div class="out">
        <div class="in a"></div>
        <div class="in b"></div>
        <div class="in c"></div>
        <div></div>
      <!-- CSS 程式碼 -->
      <style>
        .out {
          width: 350px;
          height:250px;
          overflow: scroll;      /* 隱藏超出範圍的子元素並出現捲軸 */
          padding: 20px;
          border: 1px solid #000;  
          background: repeating-linear-gradient(45deg,#fff 0,  #fff 25px,#eee 25px, #eee 50px); /* 用漸層背景讓效果更明顯 */
          background-attachment: local; /* 固定背景 */
        div:not([class]) {
          width: 400px;
          height: 1000px;
          clear: both;
        .in {
          width: 100px;
          height: 100px;
          margin: 5px;
          float: left;
          background: red;
          animation-name: oxxo;          /* 動畫名稱 */
          animation-fill-mode: forwards; /* 動畫結束後停留在最後一格 */
          animation-timeline: scroll();  /* 根據捲軸播放動畫進度 */
        /* 動畫設定 */
        @keyframes oxxo {
          0% {background: red;}
          100% {
            background: black;
            height: 300px;
        .a {animation-range: 10px 100px;}  /* 動畫範圍是捲軸移動的 10px~100px */
        .b {animation-range: 50px 150px;}  /* 動畫範圍是捲軸移動的 50px~150px */
        .c {animation-range: 100px 200px;} /* 動畫範圍是捲軸移動的 100px~200px */
      </style>
      

      一但可以透過元素在「可視範圍的位置」或「捲軸位置」控制動畫進度,就更能大幅發揮 CSS 強大的動畫能力,甚至不需要 JavaScript 就能做出許多有趣的捲軸效果,可惜目前還有部分瀏覽器不支援,不過相信這種好用的功能,不久的未來應該會都支援囉。

      延伸閱讀:

    • CSS 動畫 animation
    • 純 CSS 視差滾動效果
    • 如果有任何建議或問題,可傳送「意見表單」給我,謝謝~

  •