這項基礎總覽說明如何為電視、手機、電腦等裝置建構回應式水平捲動檢視畫面。
在這篇文章中,我想分享一些想法,說明如何為網路建立水平捲動體驗,讓使用者體驗更簡單、更有彈性、更易於存取,並且可在各瀏覽器和平台 (例如電視) 上運作。試用示範模式。
如果你偏好觀看影片,請參閱這篇文章的 YouTube 版本:
總覽
我們將建構水平捲動版面配置,用於代管媒體或產品的縮圖。這個元件一開始只是簡單的 <ul>
清單,但經過 CSS 轉換後,便能提供令人滿意的流暢捲動體驗,展示圖片並將圖片套用至格狀檢視畫面。我們新增了 JavaScript,以便促進 roving-index 互動,協助鍵盤使用者略過超過 100 個項目的瀏覽。此外,實驗性媒體查詢 prefers-reduced-data
可用於將媒體捲軸轉換為輕量版標題捲軸體驗。
開始使用無障礙標記
媒體捲動器只包含幾個核心元件,以及包含項目的清單。最簡單的清單形式可以傳送到世界各地,並讓所有人清楚閱讀。使用者前往這個頁面後,可以瀏覽清單並點按連結查看項目。這是我們的無障礙基礎。
使用 <ul>
元素提供清單:
<ul class="horizontal-media-scroller">
<li></li>
<li></li>
<li></li>
...
<ul>
使用 <a>
元素讓清單項目可供互動:
<li>
<a href="#">
...
</a>
</li>
使用 <figure>
元素以語意方式表示圖片及其標題:
<figure>
<picture>
<img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
</picture>
<figcaption>Legends</figcaption>
</figure>
請注意 <img>
上的 alt
和 loading
屬性。媒體捲軸的替代文字是使用者體驗的機會,可為縮圖提供額外的背景資訊,或在圖片未載入時做為備用文字,或是為依賴螢幕閱讀器等輔助技術的使用者提供語音 UI。如要進一步瞭解,請參閱五大關鍵規則,讓替代文字符合規範。
loading
屬性接受關鍵字 lazy
,用於指出只有在圖片位於檢視區範圍內時,才應擷取這個圖片來源。這對於大型清單來說非常實用,因為使用者只會下載他們捲動至畫面中的項目圖片。
支援使用者的色彩配置偏好設定
使用 color-scheme
做為 <meta>
標記,向瀏覽器傳達網頁需要淺色和深色提供的使用者代理程式樣式。這項免費功能可提供深色模式或淺色模式,具體取決於您如何查看:
<meta name="color-scheme" content="dark light">
元標記會提供最早的信號,因此如果使用者偏好深色主題,瀏覽器就能選取深色預設畫布顏色。也就是說,在網站的不同頁面之間瀏覽時,不會在載入期間閃爍白色畫布背景。載入期間會流暢切換深色主題,讓眼睛更舒適。
如要進一步瞭解這項功能,請參閱 Thomas Steiner 的文章:https://web.dev/color-scheme/。
新增內容
有了上述 ul > li > a > figure > picture > img
的內容結構,下一個工作就是新增可捲動的圖片和標題。我已在示範中加入靜態預留位置圖片和文字,但您也可以使用自己偏好的資料來源。
使用 CSS 新增樣式
接著,CSS 會將這個一般內容清單轉換為體驗。Netflix、應用程式商店和許多其他網站和應用程式都會使用水平捲動區域,在檢視區中顯示多個類別和選項。
建立捲軸版面配置
請務必避免在版面配置中截斷內容,或使用刪節號截斷文字。許多電視機都有類似的媒體捲動器,但經常會省略內容。但這個版面配置不會!它還可讓媒體內容覆寫欄大小,讓 1 個版面配置具有足夠的彈性,可處理許多有趣的組合。
容器可透過提供預設大小做為自訂屬性,覆寫資料欄大小。這個格狀版面配置會針對欄大小提供建議,只會管理間距和方向:
.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;
}
接著,<picture>
元素會使用自訂屬性建立基礎顯示比例:一個方塊:
.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);
}
}
只要再加入幾個次要樣式,即可完成媒體捲軸的基礎結構:
.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);
}
}
設定 overflow
可設定 <ul>
,讓使用者透過清單進行捲動和鍵盤導覽,然後每個直接子項 <li>
元素都會透過取得新的 inline-block
顯示類型,移除其 ::marker
。
不過,圖片尚未回應,而且會直接從所屬的方塊中彈出。您可以使用一些大小、適合和邊框樣式,以及背景漸層來控制這些圖片,以便在延遲載入時使用:
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%)
);
}
捲動邊距
對齊網頁內容,加上從邊到邊捲動的表面區域,對於打造和諧且簡約的元件至關重要。
如要完成從邊到邊捲動版面配置,並與我們的字體排版和版面配置線對齊,請使用與 scroll-padding
相符的 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 */
}
水平捲動邊框間距錯誤修正 上方說明如何輕鬆為捲動容器設定邊框間距,但其中仍有未解決的相容性問題 (不過,在 Chromium 91 以上版本已修正)。請參閱這篇文章,瞭解相關歷史資料。簡單來說,在捲動檢視畫面中,系統不一定會考量邊框間距。
為了讓瀏覽器將邊框間距放在捲軸的結尾,我會指定每個清單中的最後一個圖形,並附加一個所需邊框間距的虛擬元素。
.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);
}
}
使用邏輯屬性可讓媒體捲動器在任何書寫模式和文件方向中運作。
捲動貼齊
捲動容器 (含有溢位內容) 可透過一行 CSS 成為固定檢視區,然後由子項指定如何與該檢視區對齊。
.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;
}
}
專注
這個元件的靈感來自於電視、應用程式商店等平台的廣泛應用。許多電玩平台都會使用類似這個的媒體捲軸,做為主要的首頁版面配置。焦點是這裡的一大使用者體驗時刻,而非只是小小的新增功能。假設你想在沙發上使用這個媒體捲動器,並透過遙控器進行互動,可以進行一些小幅改善:
.horizontal-media-scroller a {
outline-offset: 12px;
&:focus {
outline-offset: 7px;
}
@media (prefers-reduced-motion: no-preference) {
& {
transition: outline-offset .25s ease;
}
}
}
這會將焦點外框樣式 7px
設為遠離方塊,為其提供一些不錯的空間。如果使用者沒有減少動作偏好設定,系統會轉換偏移量,為焦點事件提供細微的動作。
流動索引
在這些長長的捲動內容和選項清單中,遊戲控制器和鍵盤使用者需要特別留意。解決這個問題的常見模式稱為「流動索引」。當項目容器獲得鍵盤焦點,但一次只能允許 1 個子項保留焦點時,就會發生此錯誤。這個單一可聚焦項目一次一項的體驗設計,可讓您略過可能很長的項目清單,不必按下分頁鍵 50 次以上才能到達結尾。
在示範的首個捲軸中,有 300 個項目。我們可以做得更好,不必讓他們逐一檢查所有區段,才能到達下一個區段。
如要建立這項體驗,JavaScript 需要觀察鍵盤事件和焦點事件。我建立了npm 上的一個小型開放原始碼程式庫,方便實現這種使用者體驗。以下是如何為 3 個捲軸使用此方法:
import {rovingIndex} from 'roving-ux';
rovingIndex({
element: someElement
});
這個示範會查詢捲動器的文件,並為每個捲動器呼叫 rovingIndex()
函式。傳遞 rovingIndex()
元素,以便取得漫遊體驗 (例如清單容器),以及目標查詢選擇器 (如果焦點目標不是直接子項的話)。
document.querySelectorAll('.horizontal-media-scroller')
.forEach(scroller =>
rovingIndex({
element: scroller,
target: 'a',
}))
如要進一步瞭解這項效果,請參閱開放原始碼程式庫 roving-ux。
顯示比例
截至本文撰寫時,aspect-ratio
的支援功能仍在 Firefox 的標記後方,但在 Chromium 瀏覽器或設定頂端方塊中可使用。由於媒體捲軸格線版面配置只會指定方向和間距,因此媒體查詢中的大小可以變更,這項功能會檢查是否支援顯示比例。將漸進式增強功能納入部分更具動態性的媒體捲軸。
@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);
}
}
}
}
如果瀏覽器支援 aspect-ratio
語法,媒體捲軸圖片會升級為 aspect-ratio
大小。使用草稿巢狀語法時,每張相片的顯示比例會根據其位於第一、第二或第三列而有所不同。巢狀語法也允許設定一些小型檢視區調整,並與其他大小邏輯搭配使用。
有了 CSS,由於這項功能可在更多瀏覽器引擎中使用,因此會顯示易於管理但更具視覺吸引力的版面配置。
偏好使用較少的資料
雖然下列技巧僅適用於Canary 啟用標記的情況,但我想分享如何透過幾行 CSS 大幅縮短網頁載入時間和資料使用量。第 5 級的 prefers-reduced-data
媒體查詢可詢問裝置是否處於任何減少資料狀態,例如數據節省模式。如果是的話,我可以修改文件,在這種情況下,我會隱藏圖片。
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
使用者仍可瀏覽內容,但不會下載重型圖片。以下是未加入 prefers-reduced-data
CSS 的網站:
(7 個要求,100kb 的資源,耗時 131 毫秒)
以下是加入 prefers-reduced-data
CSS 後的網站成效:
(71 個要求,1.2 mb 的資源,耗時 1.07 秒)
減少 64 個要求,也就是這個瀏覽器分頁的檢視區域內的約 60 張圖片 (在寬螢幕顯示器上進行測試)、網頁載入速度提升約 80%,以及透過網路傳輸的資料減少 10%。相當強大的 CSS。
結論
既然你知道我如何做到,你會怎麼做呢?🙂
讓我們多方嘗試,瞭解在網路上建構應用程式的所有方式。建立 Codepen 或自行發布示範內容,然後透過推文告訴我,我會將內容加入下方的社群重混部分。
資料來源
社群重混作品
尚無任何資料可提供!