建立媒體捲動工具元件

基本介紹如何針對電視、手機、電腦等裝置建構回應式橫向捲動檢視畫面。

在這篇文章中,我想分享一些方式來打造水平捲動網頁體驗,讓網頁和平台和平台 (例如電視) 的橫向捲動體驗變得最低、回應式且易於存取。立即試用示範

示範

如果你偏好使用影片,也可以觀看這篇 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> 中的 altloading 屬性。媒體捲動器的替代文字是一種使用者體驗商機,可協助提供縮圖的額外背景資訊;如果圖片無法載入,則會以備用文字呈現;如果圖片無法載入,則會提供語音 UI,供需要輔助技術 (例如螢幕閱讀器) 的使用者使用。詳情請參閱符合標準的替代文字的五大黃金規則

loading 屬性接受關鍵字 lazy,以表示只有在圖片位於可視區域中時,才應擷取此圖片來源。這對大型清單來說非常實用,因為使用者只會下載捲動畫面所找到項目的圖片。

支援使用者的色彩配置偏好設定

使用 color-scheme 做為 <meta> 標記,向瀏覽器表明網頁需要淺色和深色的使用者代理程式樣式。這個模式有免費的深色模式或淺色模式,取決於您的視角:

<meta name="color-scheme" content="dark light">

中繼標記提供最早的信號,因此如果使用者採用深色主題偏好設定,瀏覽器即可選取深色預設畫布顏色。這表示在網站頁面之間瀏覽時,不會在各網頁載入之間閃爍白色畫布背景。不同載入之間的流暢深色主題,眼睛看起來更出色。

如要瞭解詳情,請前往 Thomas Steinerhttps://web.dev/color-scheme/ 一文。

新增內容

根據上述 ul > li > a > figure > picture > img 內容結構,下一個工作是新增圖片和標題來捲動瀏覽。我們已經在示範中加入靜態預留位置圖片和文字,但您可以從喜愛的資料來源中也可以執行此操作。

使用 CSS 新增樣式

現在,CSS 會利用這份一般內容清單,將其轉換成體驗。Netflix、App Store 及其他許多網站和應用程式會使用水平捲動區域,將可視區域封裝至類別和選項。

建立捲軸版面配置

請務必避免切斷版面配置中的內容,或以刪節號避免文字截斷。許多電視機都有和本類媒體捲動器一樣,但通常都很難看在略過內容。此版面配置不會!媒體內容也可讓媒體內容覆寫欄大小,讓 1 個版面配置具有彈性,能夠處理許多有趣的組合。

已顯示 2 個捲動的資料列。一個沒有刪節號,代表其高度較高,且每個標題都能清晰易讀。另一部長度較短,而且許多標題都是以刪節號截斷。

容器可提供預設大小做為自訂屬性,藉此覆寫資料欄大小。這個格狀版面配置只涉及資料欄大小,只會管理間距和方向:

.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;
  }
}

突顯重點

這個元件的靈感來自於電視、App Store 等大受歡迎。許多電玩遊戲平台使用媒體捲軸非常類似,以作為主畫面的主要版面配置。重點是使用者體驗重大的時刻 不再只有小小的修改想像一下,在沙發上透過遙控器使用這個媒體捲軸時 可以稍做改進

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

這會將焦點外框樣式 7px 從方塊外設定,使其留出一些空間。如果使用者對減少動作沒有動作偏好設定,系統會移動偏移,為聚焦事件提供細微的動作。

旋轉索引

在這些長串捲動內容和選項清單中,遊戲手把和鍵盤使用者需要特別留意。解決這個問題的常見模式稱為「核准索引」。這指的是一個項目的容器聚焦於鍵盤,但一次只允許 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 瀏覽器或機上盒中使用。由於媒體捲軸格線版面配置只會指定方向和間距,因此大小調整功能可以在媒體查詢中進行變更,而此功能會檢查是否支援顯示比例。進一步強化一些動態媒體捲動器。

長寬比為 4:4 的方塊會顯示在其他使用 16:9 和 4:3 的設計比例旁邊

@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,由於這項功能已在更多的瀏覽器引擎中推出,因此管理方式較容易,但也更容易呈現出視覺效果更佳的版面配置。

偏好使用較少數據用量

雖然這項下一個技巧只能在初期測試旗標後方使用,但我想分享如何運用幾行 CSS 節省大量網頁載入時間和資料使用方式。第 5 級prefers-reduced-data 媒體查詢會詢問裝置是否處於任何資料縮減狀態,例如數據節省模式。如果有,我可以修改文件;在這種情況下,請隱藏圖片。

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

雖然內容仍可瀏覽,但無需下載大量圖片的代價。以下是新增 prefers-reduced-data CSS 前的網站:

(7 個要求,131 毫秒為 100 KB 的資源)

ALT_TEXT_HERE

以下是新增 prefers-reduced-data CSS 後的網站成效:

ALT_TEXT_HERE

(71 個要求,1.07 秒有 1.2 MB 的資源)

要求減少 64 則要求,也就是這個瀏覽器分頁可視區域範圍內約 60 張圖片 (以寬螢幕顯示進行測試) 和約 80% 的網頁載入,另外 10% 的資料來自線路。功能強大的 CSS

結論

現在你知道我怎麼做,你會怎麼做?🙂

讓我們帶您更多元的方法,並瞭解運用網路打造網站的所有方式。 建立 Codepen 或代管自己的示範影片,透過 Twitter 推文附上,我會將程式碼加到下方的「社群重混」部分。

資料來源

社群重混作品

這裡還沒有內容!