Understanding timeline range names
Theo mặc định, view progress timeline theo dõi các phần tử trên toàn bộ scrollport. Animation timeline bắt đầu khi pixel đầu tiên của cạnh bắt đầu phần tử đi qua cạnh kết thúc của scrollport, và kết thúc khi cạnh cuối phần tử đi qua cạnh bắt đầu của scrollport. Bạn có thể thay đổi phạm vi gắn animation mặc định này. Ví dụ, bạn có thể giới hạn view progress timeline chỉ bắt đầu khi phần tử subject đã hoàn toàn vào scrollport.
Hướng dẫn này giải thích cách chỉnh sửa tên timeline range, đặc biệt xem xét các tên timeline range khác nhau, ý nghĩa của chúng và cách chúng được sử dụng.
Sơ lược về view progress timeline
CSS animations được tạo bằng cách gắn animation @keyframes vào một phần tử dùng thuộc tính animation-name (hoặc shorthand animation). Các keyframe xác định hành vi của animation, trong khi animation-timeline xác định thời điểm và cách phần tử tiến qua các keyframe đó.
Theo mặc định, timeline của animation là DocumentTimeline dựa trên thời gian mặc định của tài liệu. Với CSS scroll-driven animations, timeline của animation — hay sự tiến triển — được điều khiển bởi cuộn của người dùng (scroll progress timeline) hoặc khả năng hiển thị của phần tử (view progress timeline), thay vì sự trôi qua của thời gian.
Với view progress timeline, sự tiến triển của keyframe được gắn với lượng phần tử subject hiển thị trong scroller và vị trí của nó trong scroller. Khi phần tử vào viewport, timeline tiến lên. Nếu người dùng đảo ngược cuộn, timeline đảo ngược. Nói cách khác, khi phần tử đi vào hoặc ra khỏi view, timeline tiến triển hoặc đảo ngược, tương ứng. Animation chỉ xảy ra khi subject hiển thị trong scrollport. Nếu cuộn dừng lại trong khi phần tử đang trong view, animation tạm dừng.
View progress timeline mặc định
Theo mặc định, tiến triển của view progress timeline bắt đầu khi cạnh bắt đầu của subject được theo dõi giao cắt với scrollport ở cạnh cuối và kết thúc khi cạnh cuối của subject thoát khỏi scrollport ở cạnh bắt đầu. Đây là các cạnh trên và dưới của subject và scrollport khi cuộn dọc, và các cạnh trái phải hoặc phải trái khi cuộn ngang, tùy thuộc vào writing mode.
Trong ví dụ sau, hãy thử cuộn xuống. Lưu ý cách animation bắt đầu ngay khi cạnh trên của phần tử được animate căn chỉnh với cạnh dưới của scroll container và kết thúc, đạt 100% tiến triển, khi cạnh dưới căn chỉnh với cạnh trên của container, bất kể phần tử được animate cao bao nhiêu.
Writing mode và hướng cuộn của scroll container xác định cạnh bắt đầu và kết thúc của scroll container.
Phạm vi gắn animation
Theo mặc định, phần tử được animate trong toàn bộ thời gian bất kỳ phần nào của phần tử subject đang hiển thị. Điều này có nghĩa là phạm vi gắn animation mặc định là tổng chiều cao của scroll container và chiều cao của phần tử subject, với chiều cao thêm vào ở cạnh cuối cuộn.
Trong ví dụ trước, scroll container cao 250px, và phần tử được animate cao 50px theo mặc định, nghĩa là phạm vi gắn animation dọc là 300px chiều cao. Khi subject được đặt thành 250px, phạm vi trở thành 500px; khi phần tử được đặt thành 500px, kích thước phạm vi gắn animation tăng lên 750px.
Module CSS scroll driven animations cung cấp các cơ chế để xác định các phạm vi gắn animation khác nhau. Các thuộc tính animation-range-start và animation-range-end, cả hai đều có thể được đặt bằng shorthand animation-range, xác định phạm vi gắn cho cạnh bắt đầu và cạnh kết thúc của phạm vi animation, cùng với bất kỳ inset nào từ cạnh nào đó, tương ứng.
Các thuộc tính animation-range chấp nhận từ khóa normal, một <timeline-range-name>, một <length-percentage>, hoặc cả <timeline-range-name> và <length-percentage>. Trong hướng dẫn này, chúng ta đang đề cập đến các giá trị cho thành phần <timeline-range-name> của giá trị.
Tên timeline range
Kiểu giá trị <timeline-range-name> chấp nhận sáu từ khóa: cover, contain, entry, exit, entry-crossing và exit-crossing. Mỗi cái đại diện cho một named timeline range được xác định trước. Named timeline range là một đoạn được đặt tên của animation timeline. Các từ khóa này cho phép nhà phát triển đặt cơ sở phạm vi gắn animation mà các offset liên quan đến đó. Điểm bắt đầu của đoạn được biểu thị là tiến triển 0% qua phạm vi; điểm kết thúc của đoạn được biểu thị là tiến triển 100% qua phạm vi. Các điểm này nằm ở đâu tùy thuộc vào phạm vi được đặt tên.
Cover
Phạm vi gắn animation trong các ví dụ trước đều "bao phủ" toàn bộ phạm vi. Phạm vi này đại diện cho toàn bộ phạm vi của view progress timeline. Tiến triển 0% đại diện cho điểm mà cạnh border bắt đầu của subject căn chỉnh với cạnh cuối của scrollport, và tiến triển 100% đại diện cho điểm mà cạnh border cuối của subject đến cạnh bắt đầu của scrollport. Như chúng ta đã thấy, kích thước của phạm vi cover là tổng của kích thước subject và scrollport theo hướng cuộn. Trong tất cả các ví dụ cho đến nay, chiều cao của phạm vi gắn animation là chiều cao của container cộng với chiều cao của phần tử được animate.
Named timeline range cover là phạm vi mặc định. Chúng ta có thể đặt <timeline-range-name> một cách tường minh để đạt được kết quả tương tự:
.animated_element {
animation-range-start: cover;
animation-range-end: cover;
}
Hình ảnh minh họa animation timeline. Vị trí của phần tử khi đạt đến dấu 0% của phạm vi gắn animation được hiển thị là khối màu vàng. Điều này đại diện cho vị trí phần tử khi keyframe from được áp dụng. Khối màu đỏ đại diện cho vị trí của phần tử subject so với scrollport khi keyframe to được áp dụng. Đây là vị trí của phần tử được animate khi đạt đến cuối animation.
Tùy thuộc vào kích thước của phần tử subject và timeline range được chọn, vị trí bắt đầu và kết thúc có thể chồng lên nhau. Các vùng chồng lên nhau (như được thấy trong các sơ đồ tiếp theo) sẽ được biểu thị bằng các vùng kẻ sọc đỏ và vàng.
Contain
Named timeline range contain chứa toàn bộ animation trong scrollport — phạm vi bắt đầu khi phần tử được animate hiển thị 100% và kết thúc khi nó không còn hiển thị hoàn toàn, nếu nó có thể hiển thị hoàn toàn.
Giá trị contain đại diện cho phạm vi mà trong đó hộp chính hoặc được scrollport chứa hoàn toàn hoặc bao phủ hoàn toàn phạm vi hiển thị của view progress trong scrollport, tùy thuộc vào việc phần tử subject nhỏ hơn (có thể được scrollport chứa hoàn toàn) hay lớn hơn scrollport.
-
Nếu phần tử nhỏ hơn scrollport theo hướng cuộn,
0%xảy ra khi cạnh border cuối của phần tử được animate căn chỉnh với cạnh cuối của scrollport, và100%xảy ra khi cạnh border bắt đầu của phần tử được animate căn chỉnh với cạnh bắt đầu của scrollport. Nói cách khác, giá trịcontaintrải dài từ điểm mà phần tử subject lần đầu tiên được scrollport chứa hoàn toàn (0%), đến điểm mà nó không còn được scrollport chứa hoàn toàn (100%). -
Nếu phần tử lớn hơn scrollport, tiến triển
0%là khi cạnh border bắt đầu của phần tử được animate đạt đến cạnh bắt đầu của scrollport, và100%là khi cạnh border cuối căn chỉnh với cạnh cuối. Nói cách khác, nếu animation lớn hơn container của nó, phần tử được animate không bao giờ hiển thị hoàn toàn vì nó không được "chứa" trong scrollport. Animation bắt đầu khi cạnh bắt đầu đạt đến cạnh bắt đầu của scrollport, và kết thúc khi cạnh cuối của phần tử được animate đạt đến cạnh cuối của container. -
Nếu phần tử được animate có cùng kích thước với container của nó, animation vẫn xảy ra, nhưng trong
0px, không hiển thị với người dùng.
.animated_element {
animation-range: contain;
}
Trong ví dụ này, chiều cao ban đầu của phần tử được animate là 20% chiều cao của scrollport và do đó có thể được chứa hoàn toàn trong nó. Kết quả là, như đã giải thích trước, animation sẽ bắt đầu ngay khi phần tử bắt đầu vào scrollport và kết thúc ngay khi nó bắt đầu rời đi.
Nếu bạn chọn nút radio 500px, subject trở nên gấp đôi chiều cao của scrollport. Phạm vi animation bắt đầu khi phần tử subject lần đầu bao phủ hoàn toàn scroll port, với 0% xảy ra khi cạnh bắt đầu đạt đến cạnh bắt đầu của container. Nó kết thúc khi phần tử không còn bao phủ hoàn toàn scrollport, với 100% xảy ra khi cạnh cuối vượt qua cạnh cuối của container.
Khi subject có cùng kích thước với scroll container, như xảy ra khi 250px được chọn, animation vẫn xảy ra, nhưng trong 0px. Vì 0% và 100% xảy ra cùng lúc, animation là tức thời. Sự khác biệt về styling chỉ có thể nhận ra vì các thuộc tính được định nghĩa trong trạng thái keyframe 100% được áp dụng sau khi animation kết thúc. Điều này vì thuộc tính animation-fill-mode được đặt thành forwards. Nếu không, subject cỡ trung bình 250px, có cùng chiều cao với scroll container, sẽ dường như không animate gì cả.
Animation xảy ra khi phần tử nằm trong các vùng được biểu thị bởi vùng trắng của container trong ví dụ 50px và bởi các vùng đỏ/vàng trong ví dụ 250px và 500px.
Có thể hữu ích khi so sánh và đối chiếu các giá trị cover và contain. Chúng ta có thể dùng shorthand animation-range để đặt các thuộc tính animation-range-start và animation-range-end thành cùng giá trị <animation-name-range>:
#A {
animation-range: contain;
}
#B {
animation-range: cover;
}
Chọn các nút radio khác nhau và cuộn scrollport để so sánh hiệu ứng của các giá trị cover và contain trên animation timeline.
Hãy xem xét các giá trị từ khóa <timeline-range-name> khác!
Entry và exit
Để làm cho toàn bộ animation chỉ xảy ra khi subject đang trong quá trình vào hoặc rời khỏi scrollport, hãy dùng các giá trị entry hoặc exit, tương ứng. Với hai giá trị này, phạm vi gắn animation dựa trên kích thước của phần tử được animate, không phải kích thước của scrollport.
Entry
Với entry, tiến triển 0% xảy ra vào thời điểm phần tử được animate bắt đầu vào scrollport, khi cạnh bắt đầu của subject vượt qua cạnh cuối của scrollport.
Toàn bộ animation xảy ra khi subject đi vào view, kết thúc khi nó trở nên hoàn toàn hiển thị hoặc khi đạt đến cạnh bắt đầu; cái nào xảy ra trước. Nếu phần tử được animate nhỏ hơn scrollport, phạm vi gắn animation là kích thước của subject.
Vị trí ở tiến triển 0% được hiển thị màu vàng. Vị trí ở tiến triển 100% được hiển thị màu đỏ. Khi phần tử được animate lớn hơn scrollport, hai vị trí này chồng lên nhau, được biểu thị bằng nền kẻ sọc.
Với entry, phạm vi gắn animation là kích thước của phần tử được animate hoặc kích thước của container, cái nào nhỏ hơn. Nếu subject lớn hơn scrollport, phạm vi gắn animation là toàn bộ scrollport. Với entry, 100% xảy ra khi cạnh cuối của subject vượt qua cạnh cuối của scrollport hoặc, nếu phần tử được animate lớn hơn scrollport theo hướng cuộn, khi cạnh bắt đầu của phần tử được animate đạt đến cạnh bắt đầu của scrollport.
Đặt animation-range-start: entry giống với đặt animation-range-start: cover.
Đặt animation-range-end: entry tương đương với đặt animation-range-end: contain.
Exit
Giá trị exit là nghịch đảo của entry.
Với exit, phạm vi gắn bắt đầu khi cạnh bắt đầu của phần tử được animate vượt qua cạnh bắt đầu của scrollport.
Tiến triển 0% xảy ra khi cạnh bắt đầu của subject đạt đến cạnh bắt đầu của scrollport.
Tiến triển 100% xảy ra khi cạnh cuối của subject vượt qua cạnh bắt đầu.
Đặt animation-range-start: exit 0% tương đương với đặt animation-range-start: contain 100%.
Đặt animation-range-end: exit 100% tương đương với animation-range-end: cover 100%.
So sánh entry và exit
Có thể hữu ích khi xem entry và exit cạnh nhau để hiểu tác động của kích thước subject lên phạm vi gắn animation: với hai giá trị này, phạm vi gắn animation không bao giờ lớn hơn container.
#A {
animation-range: entry;
}
#B {
animation-range: exit;
}
Cuộn viewbox để xem phạm vi của các giá trị entry và exit, sau đó thay đổi kích thước của các subject bằng nút radio và cuộn lại.
Khi các subject đủ nhỏ để được chứa hoàn toàn trong scrollport, phạm vi gắn animation timeline nằm ở đầu (entry) hoặc cuối (exit) của scrollport và kích thước của phạm vi gắn bị giới hạn theo kích thước của phần tử được animate theo hướng cuộn.
Với entry và exit, phạm vi animation được giới hạn theo kích thước của scrollport, trong khi phần tử thì không.
Nếu phần tử subject có kích thước bằng scrollport hoặc lớn hơn:
- Trong trường hợp
entry, animation kết thúc khi phần tử bao phủ hoàn toàn scrollport theo hướng cuộn. - Trong trường hợp
exit, animation không bắt đầu cho đến khi phần tử bao phủ hoàn toàn scrollport theo hướng cuộn.
Đây có thể không phải là hiệu ứng bạn muốn. Nếu bạn muốn animation entry tiếp tục chạy cho đến khi toàn bộ phần tử đã hoàn thành việc vào cạnh bắt đầu của scrollport, hoặc nếu bạn muốn animation exit bắt đầu ngay khi phần tử bắt đầu thoát khỏi cạnh cuối của scrollport, bạn cần dùng entry-crossing và exit-crossing.
Entry- và exit-crossing
Nếu phần tử subject nhỏ hơn scrollport và bạn muốn toàn bộ animation xảy ra khi nó vào hoặc thoát khỏi scrollport, bạn có thể dùng entry hoặc exit, tương ứng.
Khi subject lớn hơn scrollport, animation không chạy toàn bộ quá trình phần tử vào hoặc thoát scrollport. Giá trị entry đặt tiến triển 100% ở thời điểm cạnh bắt đầu của phần tử đạt đến cạnh bắt đầu của scrollport, trước khi phần tử đã vào scrollport hoàn toàn. Với exit, tiến triển 0% xảy ra khi cạnh cuối của phần tử đạt đến cạnh cuối của scroll container, khi một phần của subject đã thoát khỏi scrollport. Với cả hai giá trị này, phạm vi gắn animation nhỏ hơn subject. Nếu đây không phải là hiệu ứng bạn muốn, các giá trị *-crossing có thể là giải pháp bạn tìm kiếm.
Entry-crossing
Giá trị entry-crossing đại diện cho phạm vi mà trong đó phần tử được animate vượt qua cạnh cuối của scrollport, với tiến triển 0% xảy ra khi cạnh bắt đầu của phần tử căn chỉnh với cạnh cuối của scrollport và tiến triển 100% xảy ra khi cạnh cuối của phần tử đạt đến cạnh cuối của scrollport, nghĩa là nó đã hoàn toàn cuộn vào scrollport.
Có thể hữu ích khi so sánh hai giá trị trong ví dụ trực tiếp.
#A {
animation-range: entry;
}
#B {
animation-range: entry-crossing;
}
Chọn các giá trị chiều cao khác nhau, sau đó cuộn để so sánh entry với entry-crossing cho mỗi kích thước.
Lưu ý cách các hiệu ứng tương tự nhau, ngoại trừ khi 500px được chọn và phần tử được animate cao hơn container.
Phạm vi entry-crossing tạo ra kết quả giống như entry khi phần tử bằng hoặc nhỏ hơn scrollport, nhưng khi phần tử lớn hơn scrollport, 100% xảy ra muộn hơn, chỉ khi cạnh cuối đã vào viewport.
Phạm vi gắn animation là kích thước của subject, không bị giới hạn bởi kích thước của scrollport.
Exit-crossing
Giá trị exit-crossing đại diện cho phạm vi mà trong đó phần tử được animate vượt qua cạnh bắt đầu của scrollport, với tiến triển 0% xảy ra khi cạnh bắt đầu của phần tử căn chỉnh với cạnh bắt đầu của scrollport và tiến triển 100% xảy ra khi cạnh cuối của phần tử đạt đến cạnh bắt đầu của scrollport.
Với exit-crossing, animation bắt đầu ngay khi subject bao phủ scrollport (với exit, animation không bắt đầu cho đến khi cạnh cuối của subject đi vào view). Trong cả hai trường hợp, animation tiếp tục cho đến khi subject hoàn toàn thoát khỏi cạnh bắt đầu của scrollport.
#A {
animation-range: exit;
}
#B {
animation-range: exit-crossing;
}
exit-crossing tạo ra kết quả giống như exit khi phần tử bằng hoặc nhỏ hơn scrollport, nhưng khi phần tử lớn hơn scrollport, 0% xảy ra sớm hơn, xảy ra ngay khi cạnh bắt đầu của phần tử đạt đến cạnh bắt đầu của scrollport, thay vì chờ đến khi cạnh cuối của phần tử vào scrollport.
Giống như với entry-crossing, phạm vi gắn animation là kích thước của subject, không bị giới hạn bởi kích thước của scrollport.
Xem thêm
- Kiểu dữ liệu
<timeline-range-name> - Keyframe selectors
- Scroll-driven animation timelines
- Module Scroll-driven animation
- Module CSS animations
- Web Animations API