Thông tin tổng quan cơ bản về cách tạo 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ề 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.
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 đó. 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 đó. Khi vuốt sang phải, người dùng sẽ chuyển sang 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. Tương tự như có một băng chuyền bên trong mỗi băng chuyền. 🤯
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 bạn bè
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;
}
Hãy cùng 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
100vh
và100vw
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ộtauto-flow
dịch sanggrid-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 coi 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 ta muốn các tin stories của bạn bè tiếp tục bên ngoài khung nhìn để có nơi 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à một 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 đóng hộp chính xác 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 chụp nhanh cuộn 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.
.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; }
.user { display: grid; grid: [story] 1fr / [story] 1fr; scroll-snap-align: start; scroll-snap-stop: always; }
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 về Đ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ái và Mũ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ẽ ngày càng 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à thông tin tóm tắt ngắn gọn về các tính năng trên 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ợ.
Tuy nhiên, chúng tôi đã không áp dụng một số CSS, vì vậy, một số nền tảng hiện đang thiếu 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. Phù hợp với mọi dịp. Thành phần Stories của tôi sử dụng thành phần này để ngăn các cử chỉ vuốt và cuộn khác 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 thích tính năng này 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 tính năng bổ sung vô hại và 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 hết các tin stories của một người bạn, đó là lúc chuyển sang người bạn tiếp theo trong nhóm điểm chụp nhanh khi cuộn. 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 vào chế độ xem. 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 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.
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
- @geoffrich_ với Svelte: bản minh hoạ và mã
- @GauteMeekOlsen với Vue: bản minh hoạ + mã
- @AnaestheticsApp với Lit: bản minh hoạ và mã