Cuộn được kiểm soát tốt bằng CSS Scroll Snap

Tạo trải nghiệm cuộn được kiểm soát tốt bằng cách khai báo các vị trí chụp nhanh cuộn.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

Tính năng CSS Scroll Snap (Cuộn nhanh CSS) cho phép nhà phát triển web tạo trải nghiệm cuộn được kiểm soát tốt bằng cách khai báo các vị trí cuộn nhanh. Bài viết được phân trang và băng chuyền hình ảnh là hai ví dụ thường dùng về điều này. CSS Scroll Snap cung cấp một API nhất quán và dễ sử dụng để tạo các mẫu trải nghiệm người dùng phổ biến này.

Thông tin khái quát

Trường hợp sử dụng tính năng cuộn nhanh

Cuộn là một cách phổ biến và tự nhiên để tương tác với nội dung trên web. Đây là phương thức gốc của nền tảng để cung cấp quyền truy cập vào nhiều thông tin hơn so với lượng thông tin hiển thị trên màn hình cùng một lúc, đặc biệt quan trọng trên các nền tảng di động có không gian màn hình hạn chế. Vì vậy, không có gì ngạc nhiên khi các tác giả web ngày càng thích sắp xếp nội dung thành danh sách phẳng có thể cuộn thay vì hệ phân cấp sâu.

Nhược điểm chính của tính năng cuộn là thiếu độ chính xác. Hiếm khi một cuộn kết thúc được căn chỉnh với một đoạn văn hoặc câu. Điều này càng rõ ràng hơn đối với nội dung được phân trang hoặc được liệt kê có ranh giới có ý nghĩa khi thao tác cuộn kết thúc ở giữa trang hoặc hình ảnh, khiến nội dung đó chỉ hiển thị một phần. Những trường hợp sử dụng này sẽ được hưởng lợi từ trải nghiệm cuộn được kiểm soát tốt.

Các nhà phát triển web từ lâu đã dựa vào các giải pháp dựa trên JavaScript để kiểm soát thao tác cuộn nhằm giải quyết điểm yếu này. Tuy nhiên, các giải pháp dựa trên JavaScript không cung cấp giải pháp đầy đủ về độ trung thực do thiếu các nguyên hàm tuỳ chỉnh cuộn hoặc quyền truy cập vào tính năng cuộn kết hợp. CSS Scroll Snap đảm bảo một giải pháp nhanh chóng, có độ chân thực cao và dễ sử dụng, hoạt động nhất quán trên các trình duyệt.

CSS Scroll Snap cho phép tác giả web đánh dấu từng vùng chứa cuộn bằng các ranh giới cho các thao tác cuộn cần hoàn tất. Sau đó, trình duyệt sẽ chọn vị trí kết thúc phù hợp nhất tuỳ thuộc vào thông tin cụ thể của thao tác cuộn, bố cục và chế độ hiển thị của vùng chứa cuộn cũng như thông tin chi tiết về các vị trí chụp nhanh, sau đó tạo ảnh động mượt mà cho vị trí đó. Quay lại ví dụ trước, khi người dùng cuộn xong băng chuyền, hình ảnh hiển thị sẽ tự động căn chỉnh vào đúng vị trí. JavaScript không cần điều chỉnh cuộn.

Ví dụ về cách sử dụng tính năng cuộn nhanh css với băng chuyền hình ảnh.
Ví dụ về cách sử dụng tính năng cuộn nhanh css với băng chuyền hình ảnh. Ở đây, tính năng cuộn chụp nhanh đảm bảo rằng khi cuộn xong, tâm ngang của hình ảnh sẽ được căn chỉnh với tâm ngang của vùng chứa cuộn.

Tính năng cuộn chụp nhanh CSS

Cuộn chụp nhanh là hành động điều chỉnh độ dời cuộn của vùng chứa cuộn để ở vị trí chụp nhanh ưu tiên sau khi thao tác cuộn kết thúc.

Bạn có thể chọn vùng chứa cuộn để chụp nhanh bằng cách sử dụng thuộc tính scroll-snap-type. Thao tác này cho trình duyệt biết rằng trình duyệt nên cân nhắc chụp nhanh vùng chứa cuộn này vào các vị trí chụp nhanh do các phần tử con tạo ra. scroll-snap-type xác định trục cuộn: x, y hoặc both và độ nghiêm ngặt của tính năng chụp nhanh: mandatory, proximity. Chúng ta sẽ nói thêm về các tính năng này ở phần sau.

Bạn có thể tạo vị trí chụp nhanh bằng cách khai báo căn chỉnh mong muốn trên một phần tử. Vị trí này là độ lệch cuộn tại vị trí vùng chứa cuộn gốc gần nhất và phần tử được căn chỉnh như đã chỉ định cho trục đã cho. Bạn có thể căn chỉnh theo các cách sau trên mỗi trục: start, end, center.

Căn chỉnh start có nghĩa là cạnh bắt đầu của điểm chụp nhanh vùng chứa cuộn phải khớp với cạnh bắt đầu của vùng chụp nhanh phần tử. Tương tự, các chế độ căn chỉnh endcenter có nghĩa là cạnh cuối hoặc tâm của điểm chụp nhanh vùng chứa cuộn phải khớp với cạnh cuối hoặc tâm của vùng chụp nhanh phần tử.

Ví dụ về nhiều cách căn chỉnh trên trục cuộn ngang.

Các ví dụ sau đây minh hoạ cách sử dụng các khái niệm này.

Một trường hợp sử dụng phổ biến của tính năng chụp nhanh khi cuộn là băng chuyền hình ảnh. Ví dụ: để tạo một băng chuyền hình ảnh ngang chụp nhanh đến từng hình ảnh khi bạn cuộn, chúng ta có thể chỉ định vùng chứa cuộn có scroll-snap-type bắt buộc trên trục ngang. Đặt mỗi hình ảnh thành scroll-snap-align: center để đảm bảo tính năng chụp nhanh căn giữa hình ảnh trong băng chuyền.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Vì các vị trí chụp nhanh được liên kết với một phần tử, nên thuật toán chụp nhanh có thể thông minh về thời điểm và cách thức chụp nhanh dựa trên phần tử và kích thước vùng chứa cuộn. Ví dụ: hãy xem xét trường hợp một hình ảnh lớn hơn băng chuyền. Một thuật toán chụp nhanh đơn giản có thể ngăn người dùng kéo để xem toàn bộ hình ảnh. Tuy nhiên, quy cách yêu cầu các phương thức triển khai phải phát hiện trường hợp này và cho phép người dùng tự do cuộn xung quanh trong hình ảnh đó chỉ bằng cách chụp nhanh các cạnh của hình ảnh.

Xem bản minh hoạ | Nguồn

Ví dụ: trang sản phẩm đã trải qua hành trình

Một trường hợp phổ biến khác có thể hưởng lợi từ tính năng cuộn nhanh là các trang có nhiều phần hợp lý để cuộn theo chiều dọc, ví dụ: một trang sản phẩm thông thường. scroll-snap-type: y proximity; phù hợp hơn với các trường hợp như thế này. Tính năng này không gây cản trở khi người dùng cuộn đến giữa một phần cụ thể, mà còn chụp nhanh và thu hút sự chú ý đến một phần mới khi họ cuộn đủ gần.

Sau đây là cách thực hiện việc này:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Khoảng đệm và lề cuộn

Trang sản phẩm có tiêu đề ở đầu trang ở vị trí cố định. Thiết kế này cũng yêu cầu một số phần ở trên cùng vẫn hiển thị khi vùng chứa cuộn được chụp nhanh để cung cấp cho người dùng một tín hiệu thiết kế về nội dung ở trên.

Thuộc tính scroll-padding là một thuộc tính css mới có thể dùng để điều chỉnh vùng xem hiệu quả của vùng chứa cuộn hoặc snapport (điểm chụp nhanh) được dùng khi tính toán các căn chỉnh chụp nhanh cuộn. Thuộc tính này xác định một phần lồng ghép so với hộp khoảng đệm của vùng chứa cuộn. Trong ví dụ của chúng ta, 15vh lồng ghép bổ sung được thêm vào đầu trang, hướng dẫn trình duyệt xem xét vị trí thấp hơn, 15vh bên dưới cạnh trên cùng của vùng chứa cuộn, làm cạnh bắt đầu dọc của tính năng cuộn chụp nhanh. Khi chụp nhanh, cạnh bắt đầu của phần tử mục tiêu chụp nhanh sẽ khớp với vị trí mới này, do đó để lại khoảng trống ở phía trên.

Thuộc tính scroll-margin xác định số lượng ban đầu dùng để điều chỉnh hộp hiệu quả của mục tiêu chụp nhanh tương tự như cách scroll-padding hoạt động trên vùng chứa cuộn chụp nhanh.

Bạn có thể nhận thấy rằng hai thuộc tính này không có từ "snap". Điều này là có chủ ý vì các phương thức này thực sự sửa đổi hộp cho tất cả các thao tác cuộn liên quan chứ không chỉ là cuộn chụp nhanh. Ví dụ: Chrome tính đến các giá trị này khi tính toán kích thước trang cho các thao tác cuộn trang như PageDown và PageUp, cũng như khi tính toán lượng cuộn cho thao tác Element.scrollIntoView().

Xem bản minh hoạ | Nguồn

Tương tác với các API cuộn khác

API cuộn DOM

Tính năng cuộn tự động xảy ra sau tất cả các thao tác cuộn, bao gồm cả các thao tác do tập lệnh khởi tạo. Khi bạn đang sử dụng các API như Element.scrollTo, trình duyệt sẽ tính toán vị trí cuộn dự kiến của thao tác, sau đó áp dụng logic chụp nhanh thích hợp để tìm vị trí chụp nhanh cuối cùng. Do đó, tập lệnh người dùng không cần thực hiện bất kỳ phép tính thủ công nào để chụp nhanh.

Cuộn mượt mà

Tính năng cuộn mượt kiểm soát hành vi của thao tác cuộn theo lập trình, trong khi tính năng chụp nhanh khi cuộn xác định đích đến của thao tác đó. Vì các thành phần này kiểm soát các khía cạnh vuông góc của thao tác cuộn, nên chúng có thể được sử dụng cùng nhau và bổ sung cho nhau.

Hành vi cuộn xuống cuối cùng

API hành vi cuộn xuống kiểm soát cách cuộn được liên kết trên nhiều phần tử và không bị ảnh hưởng bởi tính năng cuộn nhanh.

Lưu ý và phương pháp hay nhất

Tránh sử dụng tính năng chụp nhanh bắt buộc khi các phần tử mục tiêu có khoảng cách lớn. Điều này có thể khiến nội dung nằm giữa các vị trí chụp nhanh không truy cập được.

Trong nhiều trường hợp, bạn có thể thêm tính năng cuộn nhanh dưới dạng tính năng nâng cao mà không cần phát hiện tính năng. Nếu cần, hãy sử dụng @supports hoặc CSS.supports để phát hiện khả năng hỗ trợ tính năng Cuộn nhanh CSS. Tránh sử dụng scroll-snap-type cũng có trong thông số kỹ thuật không dùng nữa.

Phát hiện tính năng trong CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Phát hiện tính năng trong JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Đừng giả định rằng các API cuộn theo phương thức lập trình như Element.scrollTo luôn kết thúc ở độ dời cuộn được yêu cầu. Tính năng cuộn chụp nhanh có thể điều chỉnh độ dời cuộn sau khi quá trình cuộn theo lập trình hoàn tất. Xin lưu ý rằng đây không phải là giả định tốt ngay cả trước khi cuộn nhanh vì thao tác cuộn có thể bị gián đoạn vì các lý do khác, nhưng đặc biệt là trường hợp cuộn nhanh.

Công việc trong tương lai

Trải nghiệm cuộn là trọng tâm của một cuộc khảo sát gần đây của nhóm Chrome. Kết quả khảo sát đã xác định một số khía cạnh cần được cải thiện để thu hẹp khoảng cách giữa thư viện trình bổ trợ và CSS. Công việc sắp tới sẽ tập trung vào scroll-snap, bao gồm:

  1. Khả năng tương thích và phạm vi cung cấp API trên các trình duyệt.
  2. Làm việc trên các API CSS mới như scroll-start.
  3. Làm việc trên các sự kiện JS mới như snapChanged().