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í cuộn.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

Tính năng CSS Scroll Snap 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 vị trí cuộn. Bài viết được phân trang và băng chuyền hình ảnh là hai ví dụ thường dùng cho trường hợp 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 chụp nhanh khi cuộn

Cuộn là một cách tự nhiên và phổ biến để tương tác với nội dung trên web. Đây là phương tiện 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 số lượng thông tin hiển thị trên màn hình cùng một lúc, trở nên đặ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ế. 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 các 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 chức năng cuộn là thiếu chính xác. Hiếm khi một thao tác cuộn kết thúc được căn chỉnh với một đoạn hoặc câu. Điều này thậm chí còn rõ ràng hơn đối với nội dung được phân trang hoặc chia thành mục 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 được hưởng lợi từ trải nghiệm cuộn được kiểm soát tốt.

Từ lâu, các nhà phát triển web đã 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úp giải quyết thiếu sót 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 về độ chân thực đầy đủ do thiếu dữ liệu gốc tuỳ chỉnh thao tác cuộn hoặc không có quyền truy cập vào tính năng cuộn tổng hợp. CSS Scroll Snap đảm bảo một giải pháp nhanh, 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ả trang web đánh dấu từng vùng chứa cuộn bằng ranh giới cho các hoạt động cuộn đã kết thúc. Sau đó, trình duyệt 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ư chi tiết về vị trí chụp nhanh, sau đó tạo hiệu ứng động cho vị trí đó một cách mượt mà. Quay lại ví dụ trước đó của chúng ta, khi người dùng cuộn xong băng chuyền, hình ảnh hiển thị của băng chuyền sẽ khớp vào vị trí. JavaScript không cần điều chỉnh thao tác cuộn.

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

Nút cuộn CSS

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

Bạn có thể chọn sử dụng tính năng chụp nhanh vùng chứa cuộn bằng cách sử dụng thuộc tính scroll-snap-type. Điều này cho trình duyệt biết rằng 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 thành phần con cháu tạo ra. scroll-snap-type xác định trục diễn ra thao tác cuộn: x, y hoặc both và độ nghiêm ngặt khi chụp: 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 vị trí căn chỉnh mong muốn trên một phần tử. Vị trí này là độ lệch cuộn mà tại đó vùng chứa cuộn của đối tượng cấp trên gần nhất và phần tử được căn chỉnh như được chỉ định cho trục đã cho. Các cách căn chỉnh sau có thể có trên mỗi trục: start, end, center.

Căn chỉnh start có nghĩa là cạnh bắt đầu chụp nhanh của vùng chứa cuộn phải được đẩy bằng cạnh bắt đầu của vùng chụp phần tử. Tương tự, cách căn chỉnh endcenter có nghĩa là cạnh hoặc chính giữa của vùng chứa cuộn phải được lấp đầy với cạnh hoặc chính giữa của vùng chụp phần tử.

Ví dụ về cách căn chỉnh khác nhau 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 để chụp nhanh thao tác cuộn là băng chuyền hình ảnh. Ví dụ: để tạo băng chuyền hình ảnh ngang chụp 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. Hãy đặt từng hình ảnh thành scroll-snap-align: center để đảm bảo rằng phần 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ì vị trí chụp nhanh 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 phần tử cũng như 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 ngây thơ có thể ngăn người dùng xoay xung quanh để xem hình ảnh đầy đủ. Tuy nhiên, quy cách kỹ thuật này yêu cầu các phương thức triển khai để 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ỉ chụp nhanh các cạnh.

Xem bản minh hoạ | Nguồn

Ví dụ: một trang sản phẩm theo 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 chụp nhanh khi cuộn là các trang có nhiều phần logic để cuộn theo chiều dọc, chẳng hạn như một trang sản phẩm thông thường. scroll-snap-type: y proximity; là phù hợp hơn với các trường hợp như thế này. Chế độ này không can thiệp vào việc người dùng cuộn đến giữa một phần cụ thể, nhưng cũng 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:

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>

Cuộn khoảng đệm và lề

Trang sản phẩm có tiêu đề trên cùng của vị trí cố định. Thiết kế 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 đóng lại để cung cấp chỉ dẫn thiết kế cho người dùng 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 khu vực có thể xem hiệu quả của vùng chứa cuộn hoặc ảnh chụp nhanh (dùng khi tính toán căn chỉnh nhanh khi cuộn). Thuộc tính này xác định một phần lồng ghép dựa vào hộp khoảng đệm của vùng chứa cuộn. Trong ví dụ của chúng tôi, phần lồng ghép bổ sung 15vh đã được thêm vào trên cùng để 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 vùng chứa để chụp nhanh. Khi chụp, cạnh bắt đầu của phần tử mục tiêu chụp nhanh sẽ lấp đầy 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ố tiền bắt đầu dùng để điều chỉnh hộp hiệu quả 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 nhanh.

Bạn có thể nhận thấy 2 thuộc tính này không có từ "snap" trong chúng. Điều này là có chủ ý vì chúng thực sự sửa đổi hộp cho tất cả các thao tác cuộn có liên quan, chứ không chỉ là chụp nhanh khi cuộn. Ví dụ: Chrome sẽ xem xét các biến này khi tính kích thước trang cho các thao tác cuộn phâ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

Thao tác chụp nhanh xảy ra sau tất cả các thao tác cuộn, bao gồm cả những 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 phải 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 sẽ kiểm soát hành vi của một thao tác cuộn có lập trình trong khi thao tác cuộn nhanh xác định đích đến. Vì chúng kiểm soát các khía cạnh trực giao của việc cuộn, nên bạn có thể sử dụng chúng cùng nhau và bổ sung cho nhau.

Hành vi cuộn quá mức

API hành vi cuộn quá mức kiểm soát cách cuộn chuỗi trên nhiều phần tử và không bị ảnh hưởng bởi thao tác cuộn.

Những điều cần lưu ý và các phương pháp hay nhất

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

Trong nhiều trường hợp, bạn có thể thêm tính năng chụp 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 tính năng hỗ trợ CSS Scroll Snap. Tránh sử dụng scroll-snap-type (cũng có trong quy cách 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, chẳng hạn như Element.scrollTo luôn kết thúc ở độ lệch cuộn được yêu cầu. Chế độ chụp nhanh có thể điều chỉnh độ lệch cuộn sau khi cuộn có lập trình hoàn tất. Xin lưu ý rằng đây không phải là giả định hay ngay cả trước khi chụp nhanh vì thao tác cuộn có thể đã bị gián đoạn vì những lý do khác, nhưng đặc biệt là trong trường hợp xảy ra hiện tượng giật khi cuộn.

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

Một cuộc khảo sát gần đây của nhóm Chrome là trọng tâm của trải nghiệm cuộn. Kết quả khảo sát đã xác định được một số khía cạnh cần 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 sử dụng và khả năng tương thích của API trên nhiều trình duyệt.
  2. Hoạt động trên các CSS API mới như scroll-start.
  3. Xử lý các sự kiện JS mới như snapChanged().