基礎總覽:如何為電視、手機、桌機等裝置建構回應式水平捲軸檢視區塊。
在這篇文章中,我想分享如何為網頁建立水平捲動體驗,並盡量減少干擾、提高回應性、無障礙程度,以及跨瀏覽器和平台 (例如電視) 的適用性。試用示範模式。
如果比較喜歡看影片,可以觀看這篇貼文的 YouTube 版本:
總覽
我們將建構水平捲動版面配置,用於存放媒體或產品的縮圖。這個元件一開始只是簡單的 <ul>
清單,但透過 CSS 轉換後,就能提供令人滿意的流暢捲動體驗,顯示圖片並將圖片對齊格線。新增 JavaScript,方便漫遊索引互動,協助鍵盤使用者略過遍歷 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
屬性。媒體捲軸的替代文字是提升使用者體驗的好機會,可為縮圖提供額外背景資訊、在圖片未載入時做為備用文字,或為使用螢幕閱讀器等輔助技術的使用者提供語音介面。如要瞭解詳情,請參閱五大黃金法則,確保替代文字符合規定。
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>
元素都會移除 ::marker
,並取得新的顯示類型 inline-block
。
不過,圖片還不是回應式,而且會從所在方塊中爆開。使用一些大小、合身度和邊框樣式,以及延遲載入時的背景漸層,即可控制這些圖片:
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
移出方塊,讓方塊有適當的空間。如果使用者沒有減少動態效果的動作偏好設定,系統就會轉換位移,為焦點事件提供細微的動態效果。
Roving index
在這些長長的捲動內容和選項清單中,使用遊戲手把和鍵盤的使用者需要特別注意。解決這個問題的常見模式稱為「漫遊索引」。當項目容器成為鍵盤焦點,但一次只能有 1 個子項保留焦點時,這項設計一次只會聚焦於一個可聚焦的項目,讓使用者不必按 Tab 鍵 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。
顯示比例
撰寫本文時,Firefox 支援 aspect-ratio
的功能仍處於標記狀態,但 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
大小。使用草稿巢狀語法,每個圖片會根據是第一、第二或第三列,變更顯示比例。巢狀語法也允許設定一些小型的 viewport 調整項目,與其他大小調整邏輯位於同一位置。
有了這項 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 項要求,131 毫秒內有 100 KB 的資源)
加入 prefers-reduced-data
CSS 後的網站效能如下:
(71 個要求,1.2 MB 的資源,耗時 1.07 秒)
減少 64 個要求,也就是這個瀏覽器分頁視埠中的約 60 張圖片 (測試是在寬螢幕上進行),網頁載入速度提升約 80%,且透過網路傳輸的資料量減少 10%。功能強大的 CSS。
結論
現在您已瞭解我的做法,您會怎麼做呢?🙂
讓我們多元化方法,學習在網路上建構內容的所有方式。 建立 Codepen 或代管自己的試用版,然後在推文中提及我,我會將其新增至下方的「社群混音」部分。
資料來源
社群重混作品
目前沒有任何資料可提供!