TL;DR
Thuộc tính overscroll-behavior
CSS cho phép nhà phát triển ghi đè hành vi cuộn tràn mặc định của trình duyệt khi đạt đến đầu/cuối nội dung. Các trường hợp sử dụng bao gồm việc tắt tính năng kéo để làm mới trên thiết bị di động, xoá hiệu ứng ánh sáng khi cuộn quá mức và hiệu ứng đàn hồi, đồng thời ngăn nội dung trang cuộn khi nằm bên dưới một cửa sổ bật lên/lớp phủ.
Thông tin khái quát
Ranh giới cuộn và chuỗi cuộn
Cuộn là một trong những cách cơ bản nhất để tương tác với một trang, nhưng một số mẫu trải nghiệm người dùng nhất định có thể khó xử lý do các hành vi mặc định kỳ quặc của trình duyệt. Ví dụ: hãy lấy một ngăn ứng dụng có số lượng lớn mục mà người dùng có thể phải cuộn qua. Khi đến cuối, vùng chứa tràn sẽ ngừng cuộn vì không còn nội dung nào để tiêu thụ. Nói cách khác, người dùng đạt đến "ranh giới cuộn". Tuy nhiên, hãy lưu ý điều gì sẽ xảy ra nếu người dùng tiếp tục cuộn. Nội dung ở phía sau ngăn bắt đầu cuộn! Vùng chứa mẹ sẽ tiếp quản tính năng cuộn; chính trang chính trong ví dụ.
Hóa ra hành vi này được gọi là chuỗi cuộn; hành vi mặc định của trình duyệt khi cuộn nội dung. Thông thường, giá trị mặc định khá tốt, nhưng đôi khi không mong muốn hoặc thậm chí là không mong đợi. Một số ứng dụng có thể muốn cung cấp trải nghiệm người dùng khác khi người dùng chạm vào ranh giới cuộn.
Hiệu ứng kéo để làm mới
Kéo để làm mới là một cử chỉ trực quan được các ứng dụng di động như Facebook và Twitter phổ biến. Thao tác kéo xuống nguồn cấp dữ liệu mạng xã hội rồi thả ra sẽ tạo không gian mới để tải các bài đăng gần đây hơn. Trên thực tế, trải nghiệm người dùng đặc biệt này đã trở nên rất phổ biến đến mức các trình duyệt di động như Chrome trên Android cũng đã áp dụng hiệu ứng tương tự. Thao tác vuốt xuống ở đầu trang sẽ làm mới toàn bộ trang:
Đối với các trường hợp như PWA của Twitter, bạn nên tắt thao tác kéo để làm mới gốc. Tại sao? Trong ứng dụng này, có thể bạn không muốn người dùng vô tình làm mới trang. Bạn cũng có thể thấy ảnh động làm mới hai lần! Ngoài ra, bạn có thể tuỳ chỉnh thao tác của trình duyệt để phù hợp hơn với thương hiệu của trang web. Điều đáng tiếc là loại tuỳ chỉnh này rất khó thực hiện. Các nhà phát triển cuối cùng phải viết JavaScript không cần thiết, thêm trình nghe thao tác chạm không thụ động (chặn thao tác cuộn) hoặc gắn toàn bộ trang trong <div>
100vw/vh (để ngăn trang tràn). Các giải pháp này có tác động tiêu cực được ghi nhận rõ ràng đến hiệu suất cuộn.
Chúng ta có thể làm tốt hơn!
Xin giới thiệu overscroll-behavior
Thuộc tính overscroll-behavior
là một tính năng CSS mới giúp kiểm soát hành vi của những gì xảy ra khi bạn cuộn quá mức một vùng chứa (bao gồm cả chính trang). Bạn có thể sử dụng thuộc tính này để huỷ chuỗi cuộn, tắt/tuỳ chỉnh thao tác kéo để làm mới, tắt hiệu ứng đàn hồi trên iOS (khi Safari triển khai overscroll-behavior
) và nhiều thao tác khác.
Điều hay nhất là việc sử dụng overscroll-behavior
không ảnh hưởng xấu đến hiệu suất trang như các thủ thuật được đề cập trong phần giới thiệu!
Thuộc tính này có thể nhận 3 giá trị:
- tự động – Mặc định. Các thao tác cuộn bắt nguồn từ phần tử này có thể truyền đến các phần tử cấp trên.
- contain – ngăn chặn việc tạo chuỗi cuộn. Các thao tác cuộn không truyền đến các thành phần cấp trên nhưng các hiệu ứng cục bộ trong nút sẽ hiển thị. Ví dụ: hiệu ứng ánh sáng khi cuộn quá mức trên Android hoặc hiệu ứng đàn hồi trên iOS sẽ thông báo cho người dùng khi họ chạm đến ranh giới cuộn. Lưu ý: việc sử dụng
overscroll-behavior: contain
trên phần tửhtml
sẽ ngăn các thao tác điều hướng cuộn quá mức. - none – giống như
contain
nhưng cũng ngăn chặn các hiệu ứng cuộn hết trong chính nút (ví dụ: hiệu ứng cuộn hết trên Android hoặc hiệu ứng đàn hồi trên iOS).
Hãy cùng tìm hiểu một số ví dụ để xem cách sử dụng overscroll-behavior
.
Ngăn cuộn thoát khỏi phần tử vị trí cố định
Tình huống hộp trò chuyện
Hãy cân nhắc một hộp trò chuyện có vị trí cố định ở cuối trang. Ý định là hộp trò chuyện là một thành phần độc lập và cuộn riêng biệt với nội dung phía sau. Tuy nhiên, do tính năng tạo chuỗi cuộn, tài liệu sẽ bắt đầu cuộn ngay khi người dùng nhấn vào tin nhắn cuối cùng trong nhật ký trò chuyện.
Đối với ứng dụng này, bạn nên để các cuộn bắt nguồn từ hộp trò chuyện vẫn nằm trong cuộc trò chuyện. Chúng ta có thể thực hiện việc đó bằng cách thêm overscroll-behavior: contain
vào phần tử chứa tin nhắn trò chuyện:
#chat .msgs {
overflow: auto;
overscroll-behavior: contain;
height: 300px;
}
Về cơ bản, chúng ta đang tạo một sự phân tách hợp lý giữa ngữ cảnh cuộn của hộp trò chuyện và trang chính. Kết quả cuối cùng là trang chính vẫn ở nguyên vị trí khi người dùng đến đầu/cuối nhật ký trò chuyện. Các thao tác cuộn bắt đầu trong hộp trò chuyện không được truyền ra ngoài.
Tình huống lớp phủ trang
Một biến thể khác của trường hợp "cuộn xuống" là khi bạn thấy nội dung cuộn phía sau một lớp phủ vị trí cố định. Bạn cần có một overscroll-behavior
để tặng quà! Trình duyệt đang cố gắng hữu ích nhưng cuối cùng lại khiến trang web trông có lỗi.
Ví dụ – cửa sổ bật lên có và không có overscroll-behavior: contain
:
Tắt tính năng kéo để làm mới
Tắt thao tác kéo để làm mới chỉ bằng một dòng CSS. Chỉ cần ngăn chặn việc tạo chuỗi cuộn trên toàn bộ phần tử xác định khung nhìn. Trong hầu hết các trường hợp, đó là <html>
hoặc <body>
:
body {
/* Disables pull-to-refresh but allows overscroll glow effects. */
overscroll-behavior-y: contain;
}
Với việc bổ sung đơn giản này, chúng ta sẽ khắc phục ảnh động kéo hai lần để làm mới trong màn hình minh hoạ hộp trò chuyện và có thể triển khai hiệu ứng tuỳ chỉnh sử dụng ảnh động tải gọn gàng hơn. Toàn bộ hộp thư đến cũng bị làm mờ khi hộp thư đến làm mới:
Dưới đây là một đoạn của mã đầy đủ:
<style>
body.refreshing #inbox {
filter: blur(1px);
touch-action: none; /* prevent scrolling */
}
body.refreshing .refresher {
transform: translate3d(0,150%,0) scale(1);
z-index: 1;
}
.refresher {
--refresh-width: 55px;
pointer-events: none;
width: var(--refresh-width);
height: var(--refresh-width);
border-radius: 50%;
position: absolute;
transition: all 300ms cubic-bezier(0,0,0.2,1);
will-change: transform, opacity;
...
}
</style>
<div class="refresher">
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
</div>
<section id="inbox"><!-- msgs --></section>
<script>
let _startY;
const inbox = document.querySelector('#inbox');
inbox.addEventListener('touchstart', e => {
_startY = e.touches[0].pageY;
}, {passive: true});
inbox.addEventListener('touchmove', e => {
const y = e.touches[0].pageY;
// Activate custom pull-to-refresh effects when at the top of the container
// and user is scrolling up.
if (document.scrollingElement.scrollTop === 0 && y > _startY &&
!document.body.classList.contains('refreshing')) {
// refresh inbox.
}
}, {passive: true});
</script>
Tắt hiệu ứng ánh sáng khi cuộn quá mức và hiệu ứng cao su
Để tắt hiệu ứng bật lại khi chạm vào ranh giới cuộn, hãy sử dụng overscroll-behavior-y: none
:
body {
/* Disables pull-to-refresh and overscroll glow effect.
Still keeps swipe navigations. */
overscroll-behavior-y: none;
}
Bản minh hoạ đầy đủ
Khi kết hợp tất cả, bản minh hoạ hộp trò chuyện đầy đủ sẽ sử dụng overscroll-behavior
để tạo ảnh động kéo để làm mới tuỳ chỉnh và tắt tính năng cuộn để thoát khỏi tiện ích hộp trò chuyện. Điều này mang lại trải nghiệm người dùng tối ưu mà bạn khó có thể đạt được nếu không có CSS overscroll-behavior
.