Hiệu ứng cho trang trình bày trong băng chuyền là một cách hiệu quả để tăng sức hấp dẫn về mặt hình ảnh cho băng chuyền. Khi người dùng di chuyển qua các trang trình bày, mỗi trang trình bày có thể tạo ảnh động khi vào, căn giữa và thoát khỏi cổng cuộn. Ví dụ: các trang trình bày có thể mờ dần và hiện rõ dần, xoay hoặc điều chỉnh kích thước. Điều này tạo ra trải nghiệm người dùng linh động và hấp dẫn. Không giống như ảnh động vào/ra đơn giản, hiệu ứng này sử dụng một ảnh động liên tục để kiểm soát giao diện của trang trình bày trên toàn bộ cổng cuộn.
Cách triển khai
Sau đây là cách tạo hiệu ứng cho trang trình bày băng chuyền:
Tạo thanh cuộn: Phần tử này sẽ đóng vai trò là vùng chứa cho các trang trình bày trong băng chuyền. Trong ví dụ này,
overflow-x: scrollđược dùng để cho phép cuộn theo chiều ngang.<ul class="scroller"> <li class="entry">1</li> <li class="entry">2</li> <li class="entry">3</li> … </ul>.scroller { overflow-x: scroll; }Xác định ảnh động: Tạo ảnh động CSS xác định các trạng thái khác nhau của trang trình bày khi chúng di chuyển qua cổng cuộn. Bạn có thể xác định khung hình chính cho bất kỳ phần nào của ảnh động. Ví dụ: bạn có thể xác định trạng thái khi các trang trình bày nằm ở giữa khung nhìn cuộn bằng cách thêm khung hình chính
50%. Trong ví dụ này, thuộc tínhscalelàm cho các trang trình bày lớn lên khi chúng đến gần tâm và thu nhỏ khi chúng di chuyển ra xa.@keyframes animate { 0% { scale: 0.5; } 50% { scale: 1; } 100% { scale: 0.5; } }Áp dụng ảnh động và
view-timeline: Đính kèm ảnh động vào các trang trình bày trong băng chuyền và liên kết ảnh động đó với mộtview-timelinetheo dõi phần tử khi phần tử đó di chuyển qua vùng chứa..scroller > * { animation: animate auto linear both; animation-timeline: view(inline); }Theo mặc định,
view()theo dõi phần tử trên trụcblock. Nếu cần theo dõi trên trụcinline, bạn có thể sử dụngview(inline).
Mã mẫu
Mã này tạo ảnh động cho các mục trong băng chuyền của một thanh cuộn ngang khi cuộn bằng dòng thời gian ẩn danh của khung hiển thị:
@keyframes animate {
0% {
scale: 0.5;
}
50% {
scale: 1;
}
100% {
scale: 0.5;
}
}
.scroller > * {
/* Applies the animation using an `auto` duration */
animation: animate auto linear both;
/* Sets the animation timeline to use an anonymous view progress timeline, tracking the element's progress through the scroller on the inline axis */
animation-timeline: view(inline);
}
Mã này tạo ảnh động cho các mục trong băng chuyền của một thanh cuộn ngang khi cuộn bằng cách sử dụng dòng thời gian của khung hiển thị được đặt tên:
@keyframes animate {
0% {
scale: 0.5;
}
50% {
scale: 1;
}
100% {
scale: 0.5;
}
}
/* This creates a named view-timeline on each carousel item. The timeline is used to drive the animation that is applied on the same element. */
.scroller > * {
/* Applies the animation using an `auto` duration */
animation: animate auto linear both;
/* Defines a named view progress timeline, tracking the element's progress through the scroller on the inline axis */
view-timeline: --item inline;
/* Sets the animation timeline to use the named view progress timeline defined above */
animation-timeline: --item;
}
Các phương pháp hay nhất
Khi sử dụng ảnh động dựa trên thao tác cuộn, bạn cần tuân thủ một số phương pháp hay nhất để đảm bảo trải nghiệm mượt mà và dễ tiếp cận:
- NÊN thêm tính năng phát hiện: Không phải trình duyệt nào cũng hỗ trợ ảnh động dựa trên thao tác cuộn. Sử dụng
@supports ((animation-timeline: view()) and (animation-range: entry))để kiểm tra khả năng hỗ trợ và cung cấp phương án dự phòng cho các trình duyệt không hỗ trợ.- BẮT BUỘC phải đưa quy trình kiểm tra
(animation-range: entry)vào đây để lọc ra những trình duyệt chỉ hỗ trợ một phần. - KHÔNG sử dụng gói
scroll-timeline-polyfillcho chiến lược dự phòng vì gói này chưa hoàn thiện tính năng và có nhiều vấn đề đã biết. - Nếu ảnh động chỉ được coi là để trang trí, hãy chọn Progressive Enhancement (Cải tiến tăng dần) và KHÔNG cung cấp phương án dự phòng.
- BẮT BUỘC phải đưa quy trình kiểm tra
- NÊN tôn trọng lựa chọn ưu tiên của người dùng: Một số người dùng muốn có ít chuyển động hơn trên web. Sử dụng truy vấn nội dung nghe nhìn
prefers-reduced-motionđể tắt hoặc giảm ảnh động cho những người dùng này. - NÊN cố gắng chỉ tạo ảnh động cho các thuộc tính CSS hiệu suất cao: Để có ảnh động mượt mà nhất, hãy chỉ tạo ảnh động cho các thuộc tính có thể được xử lý bằng luồng trình tổng hợp của trình duyệt, chẳng hạn như
transformvàopacity. Việc tạo ảnh động cho các thuộc tính khác nhưwidthhoặcheightcó thể dẫn đến các vấn đề về hiệu suất. - NÊN sử dụng đúng thứ tự khai báo: Khi sử dụng thuộc tính viết tắt
animation, hãy khai báoanimation-timelinevàanimation-rangesau thuộc tính đó để ngăn thuộc tính viết tắt đặt lại dòng thời gian.
Bạn nên sử dụng view-timeline được đặt tên khi nhiều phần tử DOM cần tạo ảnh động dựa trên cùng một dòng thời gian hoặc khi bạn cần tạo ảnh động cho các phần tử con của phần tử đã xác định view-timeline. Nếu phần tử mà bạn tạo ảnh động cũng là phần tử xác định view-timeline, thì bạn có thể sử dụng dòng thời gian xem ẩn danh bằng view().
Khi sử dụng hàm view() để tạo ảnh động dựa trên thao tác cuộn:
- KHÔNG BẮT BUỘC nêu rõ trục cần theo dõi: Khi không nhắm đến trục
blockmặc định (chẳng hạn như trong trình cuộn ngang), hãy nêu rõ trục cần theo dõi bằngview(block)hoặcview(inline).
Khi sử dụng thuộc tính view-timeline để tạo ảnh động dựa trên thao tác cuộn:
- NÊN sử dụng
<dashed-ident>CSS cho tên (ví dụ:view-timeline: --my-custom-name) - KHÔNG BẮT BUỘC nêu rõ trục cần theo dõi: Khi không nhắm đến trục
blockmặc định (chẳng hạn như trong trình cuộn ngang), hãy nêu rõ trục cần theo dõi bằngview-timeline-axis. - NÊN đảm bảo phạm vi của hoạt động tra cứu hoạt động: Khi phần tử khai báo
view-timelinekhông phải là phần tử cấp trên dạng cây phẳng của phần tử ảnh động, hãy nâng chế độ hiển thị tên củaview-timelinebằng cách sử dụngtimeline-scopetrên một phần tử cấp trên được chia sẻ.
Hỗ trợ trình duyệt và chiến lược dự phòng
Do đó, bạn thường cần có một chiến lược dự phòng.
Đối với những trình duyệt không hỗ trợ ảnh động dựa trên thao tác cuộn, bạn có thể sử dụng tính năng dự phòng để tạo lại hiệu ứng hình ảnh. Các phương án dự phòng thường được xây dựng bằng trình nghe cuộn (cho hiệu ứng ScrollTimeline) hoặc API IntersectionObserver (cho hiệu ứng ViewTimeline).
Trong các trình duyệt có hỗ trợ tích hợp cho ảnh động dựa trên thao tác cuộn, hãy LUÔN sử dụng phương thức triển khai CSS gốc vì các trình duyệt đó có hiệu suất cao hơn.
Xin lưu ý rằng không phải hiệu ứng nào cũng có thể được tạo lại bằng phương pháp dự phòng.
Cụ thể cho trường hợp sử dụng này, tập lệnh sau đây áp dụng phương án dự phòng cho các trình duyệt không hỗ trợ ảnh động dựa trên thao tác cuộn. Thành phần này sử dụng API Ảnh động web (Element.animate()) để tạo ảnh động tạm dừng cho từng mục trong băng chuyền. Sau đó, trình nghe sẽ theo dõi sự kiện scroll trên trình cuộn và cập nhật currentTime của mỗi ảnh động dựa trên tiến trình cuộn của mục trong trình cuộn.
// Fallback for browsers that don't support scroll-driven animations
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
const scroller = document.querySelector('.scroller');
const entries = document.querySelectorAll('.entry');
// Create a map to store animations
const animations = new Map();
entries.forEach(entry => {
const animation = entry.animate(
{
scale: ['0.5', '1', '0.5']
},
{
duration: 1, // We'll control the time ourselves
fill: 'both'
}
);
animation.pause();
animations.set(entry, animation);
});
// Update animations on scroll
const tick = () => {
const scrollerRect = scroller.getBoundingClientRect();
entries.forEach(entry => {
const animation = animations.get(entry);
if (!animation) return;
const entryRect = entry.getBoundingClientRect();
const progress = (entryRect.left + entryRect.width / 2 - scrollerRect.left) / scrollerRect.width;
animation.currentTime = progress;
});
};
scroller.addEventListener('scroll', tick);
tick();
}