Xây dựng thành phần Stories

Tổng quan cơ bản về cách xây dựng trải nghiệm tương tự như Instagram Stories trên web.

Trong bài đăng này, tôi muốn chia sẻ suy nghĩ về cách xây dựng một thành phần Stories cho web có khả năng thích ứng, hỗ trợ di chuyển bằng bàn phím và hoạt động trên nhiều trình duyệt.

Bản minh hoạ

Nếu bạn muốn xem ví dụ thực tế về cách tự xây dựng thành phần Stories, hãy tham khảo lớp học lập trình về thành phần Stories.

Nếu bạn thích video, đây là phiên bản YouTube của bài đăng này:

Tổng quan

Hai ví dụ phổ biến về trải nghiệm người dùng của Stories là Stories trên Snapchat và Instagram Stories (chưa kể đến các nhóm). Nhìn chung, Stories thường có dạng nhấn tập trung vào thiết bị di động để khám phá nhiều gói thuê bao. Ví dụ: trên Instagram, người dùng mở một tin bài của một người bạn và xem qua các ảnh trong tin bài đó. Chúng thường làm việc này với nhiều bạn bè cùng một lúc. Bằng cách nhấn vào bên phải thiết bị, người dùng sẽ chuyển thẳng đến câu chuyện tiếp theo của người bạn đó. Bằng cách vuốt sang phải, người dùng sẽ bỏ qua để đến một người bạn khác. Thành phần Story khá giống với băng chuyền, nhưng cho phép điều hướng một mảng đa chiều thay vì một mảng một chiều. Như thể có một băng chuyền bên trong mỗi băng chuyền. 🤯

Mảng đa chiều được trực quan hoá bằng thẻ. Trái sang phải là một ngăn xếp các thẻ có viền màu tím và bên trong mỗi thẻ có từ 1 đến nhiều thẻ có viền màu lục lam. Liệt kê trong một danh sách.
Băng chuyền đầu tiên về bạn bè
Băng chuyền câu chuyện thứ 2 "xếp chồng"
👍 Liệt kê trong một danh sách, còn gọi là một mảng đa chiều

Chọn công cụ phù hợp cho công việc

Nhìn chung, tôi thấy thành phần này khá dễ xây dựng, nhờ có một số tính năng quan trọng của nền tảng web. Hãy cùng tìm hiểu kỹ hơn nhé!

Lưới CSS

Bố cục của chúng tôi hoá ra có thứ tự không cao đối với Lưới CSS vì có trang bị một số cách hiệu quả để sắp xếp nội dung.

Bố cục bạn bè

Trình bao bọc thành phần .stories chính của chúng tôi là chế độ xem cuộn ngang ưu tiên thiết bị di động:

.stories {
  inline-size: 100vw;
  block-size: 100vh;

  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;

  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}

/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
  max-inline-size: 480px;
  max-block-size: 848px;
}
Sử dụng Chế độ thiết bị của Công cụ của Chrome cho nhà phát triển để làm nổi bật các cột do Lưới tạo ra

Hãy phân tích bố cục grid đó:

  • Chúng ta điền rõ ràng kích thước này vào khung nhìn trên thiết bị di động bằng 100vh100vw, đồng thời giới hạn kích thước này trên máy tính
  • / phân tách các mẫu hàng và cột
  • auto-flow dịch sang grid-auto-flow: column
  • Mẫu luồng tự động là 100%, mà trong trường hợp này, mẫu này là bất kỳ chiều rộng cửa sổ cuộn nào

Trên điện thoại di động, hãy hình dung điều này như kích thước hàng là chiều cao khung nhìn và mỗi cột là chiều rộng khung nhìn. Tiếp tục với ví dụ về Snapchat Stories và Instagram Stories, mỗi cột sẽ là một câu chuyện của một người bạn. Chúng ta muốn câu chuyện về bạn bè tiếp tục bên ngoài khung nhìn, vì vậy chúng ta có nơi nào đó để cuộn sang. Lưới sẽ tạo số lượng cột cần thiết để bố trí HTML của bạn cho mỗi câu chuyện bạn bè, từ đó tạo ra một vùng chứa cuộn động và thích ứng cho chúng ta. Lưới giúp chúng ta tập trung toàn bộ hiệu ứng.

Kết hợp các chương trình khuyến mãi

Đối với mỗi người bạn, chúng ta cần câu chuyện của họ ở trạng thái sẵn sàng phân trang. Để chuẩn bị cho hoạt ảnh và các mẫu hình thú vị khác, tôi đã chọn một ngăn xếp. Khi tôi nói đến ngăn xếp, ý tôi là bạn đang nhìn xuống một chiếc bánh mì kẹp, chứ không giống như bạn nhìn từ một bên.

Với lưới CSS, chúng ta có thể xác định lưới một ô (tức là hình vuông), trong đó các hàng và cột dùng chung một đại diện ([story]), sau đó mỗi thành phần con được gán vào không gian ô đơn có bí danh đó:

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  …
}

Việc này giúp HTML kiểm soát được thứ tự xếp chồng và cũng giữ cho tất cả các phần tử đều hoạt động. Hãy lưu ý rằng chúng ta không cần làm gì với vị trí absolute hoặc z-index, cũng như không cần đánh dấu vào ô chính xác với height: 100% hoặc width: 100%. Lưới mẹ đã xác định kích thước của khung nhìn ảnh câu chuyện, vì vậy, bạn không cần yêu cầu thành phần câu chuyện nào trong số này lấp đầy khung nhìn!

Điểm chụp nhanh cuộn CSS

Thông số kỹ thuật CSS Scroll Snap Points giúp bạn có thể khoá các phần tử vào khung nhìn khi cuộn. Trước khi những thuộc tính CSS này tồn tại, bạn phải sử dụng JavaScript và nói một cách đơn giản là điều này... phức tạp. Hãy xem bài viết Giới thiệu CSS Scroll Snap Points của Sarah Drasner để biết nội dung phân tích chi tiết về cách sử dụng những điểm này.

Thao tác cuộn theo chiều ngang không có và không có kiểu scroll-snap-points. Nếu không có, người dùng có thể cuộn tự do như bình thường. Cùng với công cụ này, trình duyệt sẽ đặt nhẹ nhàng trên từng mục.
parent
.stories {
  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}
Thành phần mẹ có thao tác cuộn quá mức xác định hành vi chụp nhanh.
đứa trẻ
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
Trẻ chọn làm mục tiêu chụp nhanh.

Tôi chọn Scroll Snap Points vì một số lý do:

  • Hỗ trợ tiếp cận miễn phí. Thông số kỹ thuật Scroll Snap Points cho biết rằng thao tác nhấn phím Mũi tên tráiMũi tên phải sẽ di chuyển qua các điểm chụp theo mặc định.
  • Thông số kỹ thuật ngày càng tăng. Thông số kỹ thuật Scroll Snap Points liên tục nhận được các tính năng và điểm cải tiến mới. Điều này có nghĩa là thành phần Stories của tôi có thể sẽ chỉ cải thiện từ nay về sau.
  • Dễ triển khai. Điểm chụp nhanh cuộn được xây dựng thực tế cho trường hợp sử dụng phân trang theo chiều ngang tập trung vào thao tác chạm.
  • Quá trình quán tính kiểu nền tảng tự do. Mọi nền tảng sẽ cuộn và nghỉ theo kiểu riêng, khác với quán tính được chuẩn hoá, vốn có thể có kiểu cuộn và nghỉ độc đáo.

Khả năng tương thích trên nhiều trình duyệt

Chúng tôi đã thử nghiệm trên Opera, Firefox, Safari và Chrome, cùng với Android và iOS. Dưới đây là tóm tắt ngắn gọn về các tính năng web, trong đó chúng tôi tìm thấy sự khác biệt về chức năng và dịch vụ hỗ trợ.

Mặc dù chúng tôi có một số CSS không được áp dụng, vì vậy, một số nền tảng hiện đang bỏ lỡ các tính năng tối ưu hoá trải nghiệm người dùng. Tôi rất thích không phải quản lý những tính năng này và cảm thấy tự tin rằng cuối cùng chúng sẽ đến được các trình duyệt và nền tảng khác.

scroll-snap-stop

Băng chuyền là một trong những trường hợp sử dụng chính của trải nghiệm người dùng đã thúc đẩy việc tạo thông số kỹ thuật CSS Scroll Snap Points. Không giống như Stories, băng chuyền không phải lúc nào cũng cần phải dừng trên từng hình ảnh sau khi người dùng tương tác với hình ảnh đó. Có thể bạn cũng nên thử quay nhanh băng chuyền. Mặt khác, tốt nhất là bạn nên sử dụng từng story phù hợp nhất và đó cũng chính là điều scroll-snap-stop cung cấp.

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

Tại thời điểm viết bài đăng này, scroll-snap-stop chỉ được hỗ trợ trên các trình duyệt dựa trên Chromium. Hãy xem phần Khả năng tương thích của trình duyệt để biết thông tin cập nhật. Tuy nhiên, trình chặn này không phải là trình chặn. Điều này chỉ có nghĩa là trên các trình duyệt không được hỗ trợ, người dùng có thể vô tình bỏ qua một người bạn. Vì vậy, người dùng sẽ phải thận trọng hơn hoặc chúng ta cần phải viết JavaScript để đảm bảo rằng một người bạn đã bỏ qua sẽ không bị đánh dấu là đã xem.

Vui lòng đọc thêm trong thông số kỹ thuật nếu bạn quan tâm.

overscroll-behavior

Bạn đã bao giờ cuộn qua một cửa sổ phụ khi đột nhiên bạn bắt đầu cuộn nội dung phía sau cửa sổ phụ chưa? overscroll-behavior cho phép nhà phát triển bẫy thao tác cuộn và không bao giờ để nó rời đi. Điều này phù hợp với mọi tình huống. Thành phần My Stories sử dụng giao diện này để ngăn các thao tác vuốt và cử chỉ cuộn bổ sung rời khỏi thành phần đó.

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

Safari và Opera là 2 trình duyệt không hỗ trợ tính năng này và điều này hoàn toàn ổn. Những người dùng đó sẽ có trải nghiệm cuộn quá mức như họ đã quen thuộc và có thể không bao giờ nhận thấy tính năng nâng cao này. Cá nhân tôi rất thích và muốn đưa tính năng này vào gần như mọi tính năng cuộn quá mức mà tôi triển khai. Đây là một bổ sung vô hại chỉ có thể giúp cải thiện trải nghiệm người dùng.

scrollIntoView({behavior: 'smooth'})

Khi người dùng nhấn hoặc nhấp và xem đến cuối chuỗi câu chuyện của một người bạn, đã đến lúc chuyển sang người bạn tiếp theo trong tập hợp điểm chụp nhanh cuộn. Với JavaScript, chúng tôi có thể tham chiếu đến người bạn tiếp theo và yêu cầu cuộn nó vào khung hiển thị. Khả năng hỗ trợ cho những khái niệm cơ bản này rất tuyệt vời; mọi trình duyệt đều cuộn nó vào khung hiển thị. Tuy nhiên, không phải trình duyệt nào cũng làm được điều này 'smooth'. Điều này có nghĩa là nó được cuộn vào khung hiển thị thay vì bật nhanh.

element.scrollIntoView({
  behavior: 'smooth'
})

Safari là trình duyệt duy nhất không hỗ trợ behavior: 'smooth' tại đây. Hãy xem phần Khả năng tương thích của trình duyệt để biết thông tin cập nhật.

Thực hành

Giờ bạn đã biết tôi làm việc đó như thế nào, bạn sẽ làm thế nào?! Hãy đa dạng hoá phương pháp tiếp cận của chúng ta và tìm hiểu tất cả các cách xây dựng trên web. Tạo một video Glitch, tweet tôi phiên bản của bạn và tôi sẽ thêm phiên bản đó vào phần Bản phối lại của cộng đồng ở bên dưới.

Bản phối lại của cộng đồng