Tổng quan cơ bản về cách tạo chế độ xem cuộn ngang thích ứng cho TV, điện thoại, máy tính, v.v.
Trong bài đăng này, tôi muốn chia sẻ cách tạo cuộn ngang cho web ở mức tối thiểu, phản hồi nhanh, dễ truy cập và hoạt động trên trình duyệt và nền tảng (như TV chẳng hạn!). Dùng thử bản minh hoạ.
Nếu bạn thích xem video hơn, sau đây là phiên bản của bài đăng này trên YouTube:
Tổng quan
Chúng tôi sẽ xây dựng bố cục cuộn ngang để lưu trữ hình thu nhỏ của
phương tiện hoặc sản phẩm. Thành phần này bắt đầu dưới dạng một danh sách <ul>
khiêm tốn nhưng
được chuyển đổi thông qua CSS thành trải nghiệm cuộn mượt mà và hài lòng, hiển thị
hình ảnh và ghép chúng vào một lưới. JavaScript được thêm vào để hỗ trợ
tương tác chỉ mục lưu động, giúp người dùng bàn phím bỏ qua việc truyền hơn 100 mục.
Ngoài ra, một truy vấn phương tiện thử nghiệm, prefers-reduced-data
, được dùng để biến
cuộn nội dung nghe nhìn vào
trải nghiệm cuộn tiêu đề gọn nhẹ.
Bắt đầu bằng mã đánh dấu dễ tiếp cận
Một trình cuộn nội dung đa phương tiện chỉ được tạo từ hai thành phần cốt lõi, là một danh sách chứa các mục. Đáp danh sách, ở dạng đơn giản nhất, có thể đi du lịch vòng quanh thế giới và được tiêu thụ bởi tất cả. Người dùng truy cập vào trang này có thể duyệt xem danh sách và nhấp vào đường liên kết để xem một mục. Đây là cơ sở dễ tiếp cận của chúng tôi.
Cung cấp danh sách có phần tử <ul>
:
<ul class="horizontal-media-scroller">
<li></li>
<li></li>
<li></li>
...
<ul>
Tạo tính tương tác cho các mục trong danh sách bằng phần tử <a>
:
<li>
<a href="#">
...
</a>
</li>
Sử dụng phần tử <figure>
để biểu thị hình ảnh và chú thích của hình ảnh theo ngữ nghĩa:
<figure>
<picture>
<img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
</picture>
<figcaption>Legends</figcaption>
</figure>
Hãy lưu ý các thuộc tính alt
và loading
trên <img>
. Văn bản thay thế cho nội dung nghe nhìn
Công cụ cuộn là một cơ hội trải nghiệm người dùng, giúp cung cấp thêm bối cảnh cho hình thu nhỏ hoặc
văn bản dự phòng nếu hình ảnh không tải hoặc cung cấp giao diện người dùng bằng giọng nói cho người dùng
dựa vào công nghệ hỗ trợ
như trình đọc màn hình. Tìm hiểu thêm với Five Golden
quy tắc cho ngôn ngữ thay thế tuân thủ
văn bản.
Thuộc tính loading
chấp nhận từ khoá lazy
làm cách để truyền tín hiệu về hình ảnh này
nguồn chỉ nên được tìm nạp khi hình ảnh nằm trong khung nhìn. Thông tin này có thể là
thực sự phù hợp với các danh sách lớn, vì người dùng sẽ chỉ tải hình ảnh xuống cho các mục họ
mà người dùng đã cuộn vào chế độ xem.
Hỗ trợ lựa chọn ưu tiên về bảng phối màu của người dùng
Sử dụng color-scheme
làm thẻ <meta>
để trình duyệt biết rằng trang của bạn
muốn có cả kiểu sáng và tối do tác nhân người dùng cung cấp. Bạn đang dùng chế độ tối miễn phí
hoặc chế độ sáng, tuỳ theo cách bạn xem:
<meta name="color-scheme" content="dark light">
Thẻ meta cung cấp tín hiệu sớm nhất có thể, để trình duyệt có thể chọn màu tối cho canvas mặc định nếu người dùng có giao diện tối ưu tiên. Tức là thao tác điều hướng giữa các trang trên trang web sẽ không nhấp nháy canvas màu trắng nền giữa các lần tải. Giao diện tối liền mạch giữa các lần tải, đẹp hơn nhiều trên mắt.
Tìm hiểu thêm nhiều từ Thomas Steiner tại https://web.dev/color-scheme/.
Thêm nội dung
Do cấu trúc nội dung ở trên của ul > li > a > figure > picture > img
,
nhiệm vụ tiếp theo là thêm hình ảnh và tiêu đề để cuộn qua. Tôi đã chuẩn bị bản minh hoạ
hình ảnh và văn bản giữ chỗ tĩnh, nhưng bạn có thể sử dụng tính năng này
nguồn dữ liệu ưa thích của bạn.
Thêm kiểu bằng CSS
Giờ là lúc CSS sử dụng danh sách nội dung chung này và biến nó thành một của bạn. Netflix, App Store cũng như nhiều trang web và ứng dụng khác sử dụng định dạng ngang các khu vực cuộn để đóng gói khung nhìn với các danh mục và tuỳ chọn.
Tạo bố cục trình cuộn
Bạn cần tránh cắt bỏ nội dung trong bố cục hoặc dựa vào văn bản cắt bớt bằng dấu ba chấm. Nhiều TV có thanh cuộn nội dung nghe nhìn giống như nhưng tất cả đều thường dùng đến nội dung dấu ba chấm. Bố cục này không! Phương thức này cũng cho phép nội dung đa phương tiện ghi đè kích thước cột, tạo ra 1 bố cục đủ linh hoạt để xử lý nhiều kiểu kết hợp thú vị.
Vùng chứa cho phép ghi đè kích thước cột bằng cách cung cấp kích thước mặc định như một thuộc tính tuỳ chỉnh. Bố cục lưới này quy định về kích thước cột, chỉ quản lý khoảng cách và hướng:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
margin: 0;
}
Sau đó, phần tử <picture>
sử dụng thuộc tính tuỳ chỉnh này để tạo tỷ lệ khung hình cơ sở: một hộp:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Chỉ với một vài kiểu nhỏ nữa, hãy hoàn thiện phần cơ bản của trình cuộn nội dung đa phương tiện:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
& > li {
display: inline-block; /* removes the list-item bullet */
}
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Việc đặt overflow
sẽ thiết lập <ul>
để cho phép thao tác cuộn và di chuyển bằng bàn phím
thông qua danh sách, thì mỗi phần tử con <li>
trực tiếp sẽ bị xoá ::marker
bằng cách tải kiểu hiển thị mới là inline-block
.
Tuy nhiên, hình ảnh chưa phản hồi và nhanh chóng thoát ra khỏi hộp chúng đang ở bên trong. Hãy điều chỉnh chúng bằng một số kích thước, kiểu dáng và kiểu đường viền, cũng như hiệu ứng chuyển màu khi tải từng phần:
img {
/* smash into whatever box it's in */
inline-size: 100%;
block-size: 100%;
/* don't squish but do cover the space */
object-fit: cover;
/* soften the edges */
border-radius: 1ex;
overflow: hidden;
/* if empty, show a gradient placeholder */
background-image:
linear-gradient(
to bottom,
hsl(0 0% 40%),
hsl(0 0% 20%)
);
}
Khoảng đệm cuộn
Căn chỉnh với nội dung trang, cộng với diện tích giao diện cuộn từ cạnh này sang cạnh khác quan trọng đối với thành phần hài hoà và tối giản.
Để hoàn thành bố cục cuộn tràn viền cho phù hợp với kiểu chữ của chúng tôi
và dòng bố cục, hãy sử dụng padding
khớp với scroll-padding
:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}
Sửa lỗi khoảng đệm cuộn theo chiều ngang Nội dung trên cho thấy mức độ dễ dàng thêm một vùng chứa cuộn, nhưng có một số vấn đề chưa được giải quyết về khả năng tương thích (đã khắc phục trong Chromium 91 trở lên!). Xem tại đây một chút của lịch sử, nhưng phiên bản ngắn gọn là khoảng đệm không phải lúc nào cũng được tính đến trong chế độ xem cuộn.
Để lừa trình duyệt đặt khoảng đệm ở cuối trình cuộn, tôi sẽ nhắm mục tiêu hình cuối cùng trong mỗi danh sách và thêm một phần tử giả số lượng khoảng đệm mong muốn.
.horizontal-media-scroller > li:last-of-type figure {
position: relative;
&::after {
content: "";
position: absolute;
inline-size: var(--gap);
block-size: 100%;
inset-block-start: 0;
inset-inline-end: calc(var(--gap) * -1);
}
}
Việc sử dụng các thuộc tính logic cho phép trình cuộn nội dung nghe nhìn hoạt động ở mọi chế độ ghi và hướng tài liệu.
Chụp ảnh/Cuộn
Vùng chứa cuộn có mục bổ sung có thể trở thành khung nhìn chụp nhanh với một dòng CSS, sau đó phần tử con phải chỉ định cách chúng muốn căn chỉnh với khung nhìn đó.
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block-end: calc(var(--gap) / 2);
scroll-snap-type: inline mandatory;
& figure {
scroll-snap-align: start;
}
}
Tập trung
Cảm hứng cho thành phần này đến từ việc nó rất phổ biến trên TV, trong App Store và nhiều cửa hàng khác. Nhiều nền tảng trò chơi điện tử sử dụng trình cuộn nội dung đa phương tiện tương tự như bố cục này, làm bố cục màn hình chính chính. Tập trung là trải nghiệm người dùng lớn không chỉ là một bổ sung nhỏ. Hãy tưởng tượng dùng trình cuộn nội dung nghe nhìn này từ chiếc ghế dài của bạn bằng điều khiển từ xa, hãy cải thiện một số chi tiết nhỏ cho hoạt động tương tác đó:
.horizontal-media-scroller a {
outline-offset: 12px;
&:focus {
outline-offset: 7px;
}
@media (prefers-reduced-motion: no-preference) {
& {
transition: outline-offset .25s ease;
}
}
}
Thao tác này sẽ đặt kiểu đường viền tiêu điểm 7px
cách xa hộp, tạo cho nó một chút
. Nếu người dùng không có ưu tiên chuyển động về việc giảm chuyển động, thì độ lệch
được chuyển tiếp, tạo ra chuyển động tinh tế cho sự kiện tiêu điểm.
Chỉ số lưu động
Người dùng tay điều khiển trò chơi và bàn phím cần đặc biệt chú ý trong các danh sách dài này cuộn nội dung và tuỳ chọn. Mô hình chung để giải quyết vấn đề này được gọi là chỉ mục lưu hành. Đó là khi vùng chứa các mục được lấy làm tâm điểm bằng bàn phím nhưng chỉ 1 thành phần con được phép giữ tiêu điểm cùng một lúc. Mục có thể lấy làm tâm điểm duy nhất này tại một trải nghiệm tại một thời điểm được thiết kế để cho phép bỏ qua danh sách các mục có thể dài, thay vì nhấn thẻ 50+ lần để kết thúc.
Có 300 mục trong trình cuộn đầu tiên của bản minh hoạ. Chúng tôi có thể làm tốt hơn là chuyển tải tất cả các tệp đó để đến phần tiếp theo.
Để tạo trải nghiệm này, JavaScript cần quan sát các sự kiện bàn phím và tiêu điểm các sự kiện. Tôi đã tạo một thư viện nguồn mở nhỏ trên npm để giúp người dùng này dễ dàng đạt được. Dưới đây là cách sử dụng trình cuộn cho 3 trình cuộn:
import {rovingIndex} from 'roving-ux';
rovingIndex({
element: someElement
});
Bản minh hoạ này truy vấn tài liệu cho các trình cuộn và cho mỗi trình cuộn gọi hàm
Hàm rovingIndex()
. Truyền phần tử rovingIndex()
để di chuyển
như vùng chứa danh sách và bộ chọn truy vấn mục tiêu, trong trường hợp
mục tiêu tâm điểm không phải là thành phần con trực tiếp.
document.querySelectorAll('.horizontal-media-scroller')
.forEach(scroller =>
rovingIndex({
element: scroller,
target: 'a',
}))
Để tìm hiểu thêm về hiệu ứng này, hãy xem thư viện nguồn mở roving-ux.
Tỷ lệ khung hình
Tại thời điểm viết bài đăng này, bộ phận hỗ trợ cho
aspect-ratio
ở phía sau
cờ trong Firefox nhưng khả dụng trong trình duyệt Chromium hoặc hộp giải mã tín hiệu số. Vì
bố cục lưới cuộn phương tiện chỉ xác định hướng và khoảng cách, kích thước có thể
bên trong truy vấn nội dung đa phương tiện. Tính năng này kiểm tra khả năng hỗ trợ tỷ lệ khung hình.
Cải tiến tăng dần vào một số trình cuộn nội dung đa phương tiện động.
@supports (aspect-ratio: 1) {
.horizontal-media-scroller figure > picture {
inline-size: auto; /* for a block-size driven ratio */
aspect-ratio: 1; /* boxes by default */
@nest section:nth-child(2) & {
aspect-ratio: 16/9;
}
@nest section:nth-child(3) & {
/* double the size of the others */
block-size: calc(var(--size) * 2);
aspect-ratio: 4/3;
/* adjust size to fit more items into the viewport */
@media (width <= 480px) {
block-size: calc(var(--size) * 1.5);
}
}
}
}
Nếu trình duyệt hỗ trợ cú pháp aspect-ratio
, thì hình ảnh của trình cuộn nội dung nghe nhìn sẽ
đã nâng cấp lên kích thước aspect-ratio
. Sử dụng cú pháp lồng bản nháp, mỗi hình ảnh
thay đổi tỷ lệ khung hình tuỳ theo việc đó là hàng đầu tiên, thứ hai hay thứ ba. Chiến lược phát hành đĩa đơn
cú pháp Nest cũng cho phép đặt một số
điều chỉnh khung nhìn, ngay ở đó với logic định kích thước khác.
Với CSS đó, vì tính năng này khả dụng trong nhiều công cụ trình duyệt hơn nên bạn có thể dễ dàng nhưng bố cục bắt mắt hơn sẽ hiển thị.
Ưu tiên giảm dữ liệu
Mặc dù kỹ thuật tiếp theo này chỉ có sẵn
phía sau một lá cờ ở
Canary,
Tôi muốn chia sẻ cách tôi có thể tiết kiệm đáng kể thời gian tải trang và
sử dụng dữ liệu thông qua một vài dòng CSS. Truy vấn phương tiện prefers-reduced-data
từ
Cấp độ 5 cho phép hỏi xem thiết bị có đang ở
bất kỳ trạng thái dữ liệu giảm nào, chẳng hạn như chế độ tiết kiệm dữ liệu. Nếu có, tôi có thể sửa đổi
tài liệu và trong trường hợp này, hãy ẩn hình ảnh.
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
Nội dung vẫn có thể điều hướng được mà không phải trả chi phí cho việc sử dụng các hình ảnh quá lớn
đã tải xuống. Đây là trang web trước khi thêm CSS prefers-reduced-data
:
(7 yêu cầu, 100kb tài nguyên trong 131 mili giây)
Dưới đây là hiệu suất của trang web sau khi thêm CSS prefers-reduced-data
:
(71 yêu cầu, 1,2 MB tài nguyên trong 1,07 giây)
Ít hơn 64 yêu cầu, tức là khoảng 60 hình ảnh trong khung nhìn (các thử nghiệm đã thực hiện trên màn hình rộng) của thẻ trình duyệt này, tăng tải trang khoảng 80% và 10% dữ liệu qua mạng. CSS khá mạnh mẽ.
Kết luận
Giờ bạn đã biết cách tôi thực hiện điều đó, bạn sẽ làm thế nào?! 🙂
Hãy đa dạng hoá phương pháp tiếp cận và tìm hiểu tất cả các cách xây dựng ứng dụng trên web. Tạo một Codepen hoặc lưu trữ bản minh hoạ của riêng bạn, tweet cho tôi và tôi sẽ thêm nó vào Phần bên dưới là phần các bản phối lại của cộng đồng.
Nguồn
Bản phối lại của cộng đồng
Chưa có gì để xem ở đây!