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

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

Trong bài đăng này, tôi muốn chia sẻ suy nghĩ về việc xây dựng một thành phần Stories cho web có khả năng thích ứng, hỗ trợ thao tác điều hướng 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 hướng dẫn thực hành về cách tự tạo thành phần Stories này, 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 xem video, hãy xem phiên bản video của bài đăng này trên YouTube:

Tổng quan

Hai ví dụ phổ biến về trải nghiệm người dùng của Stories là Snapchat Stories và Instagram Stories (chưa kể đến Fleets). Nói chung, về mặt trải nghiệm người dùng, Stories thường là mẫu chỉ dành cho thiết bị di động, tập trung vào thao tác nhấn để điều hướng giữa nhiều gói thuê bao. Ví dụ: trên Instagram, người dùng mở một story của bạn bè và xem các bức ảnh trong story đó. Thông thường, họ sẽ làm việc này với nhiều bạn bè cùng một lúc. Khi nhấn vào bên phải thiết bị, người dùng sẽ chuyển đến story tiếp theo của người bạn đó. Bằng cách vuốt sang phải, người dùng sẽ chuyển đế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 nhiều chiều thay vì một mảng một chiều. Giống như có một băng chuyền bên trong mỗi băng chuyền. 🤯

Mảng đa chiều trực quan hoá bằng thẻ. Từ trái sang phải là một chồng thẻ có đường viền màu tím, bên trong mỗi thẻ là 1-nhiều thẻ có đường viền màu xanh lục lam. Danh sách trong danh sách.
Băng chuyền câu chuyện thứ nhất
Băng chuyền câu chuyện "xếp chồng" thứ 2
👍 Danh sách trong một danh sách, còn gọi là 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ễ tạo, nhờ một vài tính năng quan trọng của nền tảng web. Hãy cùng tìm hiểu!

Lưới CSS

Bố cục của chúng ta không phải là một yêu cầu quá cao đối với CSS Grid vì nó được trang bị một số cách hiệu quả để sắp xếp nội dung.

Bố cục Friends

Trình bao bọc thành phần .stories chính của chúng ta là một thành phần hiển thị cuộn theo chiều 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 Chrome cho nhà phát triển để đánh dấu các cột do Lưới tạo

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

  • Chúng ta lấp đầy khung nhìn trên thiết bị di động bằng 100vh100vw và hạn chế kích thước 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 tự động chuyển là 100%, trong trường hợp 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 xem xét 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ề tính năng Stories trên Snapchat và Instagram, mỗi cột sẽ là một câu chuyện của bạn bè. Chúng tôi muốn những câu chuyện của bạn bè tiếp tục bên ngoài khung nhìn, vì thế, chúng tôi sẽ đến một nơi nào đó để cuộn đến. Lưới sẽ tạo số cột cần thiết để bố trí HTML cho mỗi tin của bạn bè, tạo một vùng chứa cuộn linh động và thích ứng cho chúng ta. Lưới giúp chúng tôi tập trung toàn bộ hiệu ứng.

Xếp chồng

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

Với lưới CSS, chúng ta có thể xác định một lưới một ô (tức là hình vuông), trong đó các hàng và cột có chung một bí danh ([story]), sau đó mỗi phần tử con sẽ được chỉ định cho không gian một ô 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;
  
}

Điều này giúp HTML kiểm soát thứ tự xếp chồng và cũng giúp tất cả các phần tử được sắp xếp hợp lý. Lưu ý rằng chúng ta không cần làm gì với vị trí absolute hoặc z-index và chúng ta không cần phải sửa lỗi hộp bằng height: 100% hoặc width: 100%. Lưới mẹ đã xác định kích thước của khung nhìn hình ảnh trong câu chuyện, vì vậy, không cần phải yêu cầu thành phầ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 về Điểm chụp nhanh cuộn CSS giúp bạn dễ dàng khoá các phần tử vào khung nhìn khi cuộn. Trước khi các thuộc tính CSS này xuất hiện, bạn phải sử dụng JavaScript và ít nhất thì việc này cũng… rắc rối. Hãy xem bài viết Giới thiệu về các điểm cuộn chụp nhanh CSS của Sarah Drasner để biết thông tin chi tiết về cách sử dụng các điểm này.

Cuộn ngang không có và 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. Với tính năng này, trình duyệt sẽ nhẹ nhàng nằm trên từng mục.
mẹ
.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ó tính năng cuộn xuống dưới cùng xác định hành vi chụp nhanh.
con
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
Thành phần con chọn trở thành mục tiêu chụp nhanh.

Tôi chọn Điểm chụp nhanh cuộn vì một số lý do:

  • Hỗ trợ tiếp cận miễn phí. Thông số kỹ thuật của Điểm chụp nhanh cuộn cho biết rằng theo mặc định, việ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 nhanh.
  • Thông số kỹ thuật ngày càng phát triển. Thông số kỹ thuật của Điểm chụp nhanh cuộn luôn có các tính năng và điểm cải tiến mới, nghĩa là thành phần Stories của tôi có thể sẽ chỉ tốt hơn từ giờ trở đi.
  • Dễ triển khai. Điểm chụp nhanh khi 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.
  • Độ trễ kiểu nền tảng tự do. Mỗi nền tảng sẽ cuộn và nghỉ theo kiểu của nền tảng đó, trái ngược với quán tính chuẩn hoá có thể có kiểu cuộn và nghỉ kỳ lạ.

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à bản tóm tắt ngắn gọn về các tính năng web mà chúng tôi nhận thấy có sự khác biệt về chức năng và khả năng hỗ trợ.

Mặc dù chúng tôi chưa áp dụng một số CSS, 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 việc không cần quản lý các tính năng này và tự tin rằng cuối cùng chúng sẽ được cung cấp cho 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 về trải nghiệm người dùng đã thúc đẩy việc tạo ra thông số kỹ thuật Điểm chụp nhanh cuộn CSS. Không giống như Stories, băng chuyền không phải lúc nào cũng cần dừng ở mỗi hình ảnh sau khi người dùng tương tác với hình ảnh đó. Bạn có thể hoặc nên nhanh chóng chuyển đổi giữa các băng chuyền. Mặt khác, bạn nên điều hướng từng câu chuyện một, và đó chính xác là những gì 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 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 bài viết Khả năng tương thích với trình duyệt để biết thông tin cập nhật. Tuy nhiê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 cẩn thận hơn hoặc chúng ta sẽ cần viết JavaScript để đảm bảo rằng người bạn đã bỏ qua không bị đánh dấu là đã xem.

Hãy đọ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ổ bật lên khi đột nhiên bạn bắt đầu cuộn nội dung phía sau cửa sổ bật lên đó chưa? overscroll-behavior cho phép nhà phát triển bẫy thao tác cuộn và không bao giờ để thao tác đó rời khỏi. Nội dung này phù hợp trong mọi trường hợp. Thành phần My Stories sử dụng thành phần này để ngăn các thao tác vuốt và 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 đó hoàn toàn bình thường. Những người dùng đó sẽ có trải nghiệm cuộn xuống dưới cùng như bình thường 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 hâm mộ và thích tính năng này trong hầu hết mọi tính năng cuộn quá mức mà tôi triển khai. Đây là một tính năng bổ sung không gây 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à đọc xong tập truyệ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 di chuyển nhanh. Với JavaScript, chúng ta có thể tham chiếu đến người bạn tiếp theo và yêu cầu cuộn người bạn đó vào chế độ xem. Hỗ trợ cơ bản cho tính năng này rất tốt; mọi trình duyệt đều cuộn thành phần hiển thị này. Tuy nhiên, không phải trình duyệt nào cũng làm như vậy 'smooth'. Điều này chỉ có nghĩa là thành phần hiển thị được cuộn vào chế độ xem thay vì được chụp 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ờ thì bạn đã biết cách tôi làm, còn bạn thì sao?! Hãy đa dạng hoá các phương pháp và tìm hiểu tất cả các cách để xây dựng trên web. Hãy tạo một Glitch, rồi twitt cho tôi phiên bản của bạn. 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