打造精選故事元件

簡要說明如何在網路上建立類似 Instagram 限時動態的體驗。

在本篇文章中,我想分享有關為網路建立 Stories 元件的想法,這個元件可回應式顯示、支援鍵盤導覽,並可跨瀏覽器運作。

示範

如果您想親自操作這個短片故事元件的建構作業,請參閱短片故事元件程式碼研究室

如果你偏好觀看影片,請參閱這篇文章的 YouTube 版本:

總覽

Snapchat Stories 和 Instagram Stories 是兩個熱門的 Stories 使用者體驗範例 (更不用說 Fleets)。就一般使用者體驗而言,短片故事通常是專為行動裝置設計的輕觸式模式,可用於瀏覽多個訂閱項目。舉例來說,在 Instagram 上,使用者會開啟好友的限時動態,並瀏覽其中的相片。他們通常會一次邀請這麼多朋友。輕觸裝置的右側,即可略過至該朋友的下一則限時動態。使用者向右滑動,即可跳到其他朋友。Story 元件與輪轉介面相當類似,但可瀏覽多維陣列,而非單維陣列。就像每個輪轉介面中都有一個輪轉介面。🤯?

使用資訊卡將多維陣列視覺化。從左到右是一系列紫色邊框資訊卡,每張資訊卡內含 1 至多個青色邊框資訊卡。清單中的清單。
第 1 個朋友輪轉介面
第 2 個「堆疊」的短片輪轉介面
👍? 清單中的清單,又稱為多維陣列

選擇合適的工具

總而言之,我發現這個元件相當容易建構,這要歸功於幾項重要的網路平台功能。讓我們來談談這些問題!

CSS 格線

我們的版面配置對 CSS GridLayout 來說並非難事,因為它具備一些強大的功能,可用於處理內容。

好友版面配置

我們的主要 .stories 元件包裝函式是行動版內容優先的水平捲軸檢視畫面:

.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;
}
使用 Chrome 開發人員工具的裝置模式,醒目顯示由 Grid 建立的資料欄

讓我們細分 grid 版面配置:

  • 我們會使用 100vh100vw 明確填滿行動裝置上的可視區域,並限制電腦上的大小
  • / 會分隔資料列和資料欄範本
  • auto-flow 會轉譯為 grid-auto-flow: column
  • 自動流程範本為 100%,在本例中,此值為捲動視窗的寬度

在手機上,您可以將列大小視為可視區域高度,而每個欄則視為可視區域寬度。接著以 Snapchat 動態和 Instagram 動態為例,每個欄會是好友的動態。我們希望好友動態繼續顯示在可視區域之外,這樣我們才能有地方捲動。格線會為每個好友故事的 HTML 版面配置建立所需的欄數,為我們建立動態且回應式捲動容器。我們使用格線將整個效果集中處理。

堆疊

每位好友的限時動態都必須處於可分頁的狀態。為了準備動畫和其他有趣的模式,我選擇了堆疊。我說的「堆疊」是指從上往下看三明治,而不是從側面看。

透過 CSS 格線,我們可以定義單格格線 (即正方形),其中行和欄會共用別名 ([story]),然後將每個子項指派給該別名單格空間:

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  
}

這樣一來,HTML 就能控制堆疊順序,並確保所有元素都能流暢呈現。請注意,我們不需要對 absolute 位置或 z-index 採取任何動作,也不需要使用 height: 100%width: 100% 修正框格。父項格線已定義故事圖片可視區的大小,因此不需要告知這些故事元件填滿可視區!

CSS 捲動精確點

CSS 捲動貼齊點規格可讓您輕鬆將元素鎖定在捲動時的可視區域中。在這些 CSS 屬性出現之前,您必須使用 JavaScript,而且這項操作至少說起來很棘手。請參閱 Sarah Drasner 的「Introducing CSS Scroll Snap Points」,瞭解如何使用這些點。

水平捲動,有無 scroll-snap-points 樣式。 如未設定,使用者仍可照常自由捲動。這樣瀏覽器就能輕鬆停留在每個項目上。
parent
.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;
}
兒童可選擇成為 Snap 目標。

我選擇了捲動貼齊點,原因如下:

  • 免費無障礙功能。捲動對齊點規格指出,按下向左鍵向右鍵時,系統應會根據預設值移動至對齊點。
  • 不斷進步的規格。捲動自動對齊點規格會持續推出新功能和改善項目,這表示我的 Stories 元件日後只會越來越好。
  • 導入難易度。捲動快照點實際上是為了以觸控為主的水平分頁用途而建構。
  • 自由平台式慣性。每個平台都會以其風格捲動和靜止,而非使用標準慣性,因為這樣可能會產生奇怪的捲動和靜止樣式。

跨瀏覽器相容性

我們在 Opera、Firefox、Safari 和 Chrome 上進行測試,也測試了 Android 和 iOS 版本。以下簡要說明我們發現的網頁功能,以及這些功能的功能和支援上的差異。

不過,我們確實有部分 CSS 不適用,因此部分平台目前無法進行使用者體驗最佳化。我很高興不需要管理這些功能,而且相信這些功能最終會在其他瀏覽器和平台上推出。

scroll-snap-stop

輪轉介面是促使建立 CSS 捲動 Snap Point 規格的主要使用者體驗用途之一。與 Stories 不同的是,使用者與輪轉介面互動後,不一定需要停在每張圖片上。快速瀏覽輪轉介面可能沒問題,甚至是鼓勵的做法。另一方面,針對 Stories 來說,逐一瀏覽是最理想的瀏覽方式,而 scroll-snap-stop 正是提供這種瀏覽方式。

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

在撰寫本文時,只有以 Chromium 為基礎的瀏覽器支援 scroll-snap-stop。如需最新資訊,請參閱瀏覽器相容性。不過,這並非阻斷條件。這只是表示在未支援的瀏覽器上,使用者可能會不小心略過好友。因此,使用者必須更加小心,否則我們必須編寫 JavaScript,確保略過的好友不會被標示為已觀看。

如有興趣,請參閱規格說明

overscroll-behavior

您是否曾經在捲動模式時,突然開始捲動模式後方的內容?overscroll-behavior 可讓開發人員擷取捲動畫面,並永遠不會讓畫面離開。適合各種場合。My Stories 元件會使用這項功能,避免其他滑動和捲動手勢離開元件。

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

Safari 和 Opera 是 2 個不支援這項功能的瀏覽器,這完全沒問題。這些使用者將獲得與過往相同的捲動體驗,可能不會注意到這項強化功能。我個人非常喜歡這項功能,並喜歡將其納入幾乎所有實作的捲動超出功能中。這項無害的新增功能只會改善使用者體驗。

scrollIntoView({behavior: 'smooth'})

當使用者輕觸或點按,並已抵達好友的限時動態集合結尾時,系統就會在捲動對齊點集合中移動至下一個好友。我們使用 JavaScript 參照下一個朋友,並要求將其捲動至可視範圍內。這個基本功能的支援情況非常好,每個瀏覽器都能將其捲動至可視範圍內。但並非所有瀏覽器都會這樣做 'smooth'。這只是表示系統已將其捲動至可視範圍,而非固定在該範圍內。

element.scrollIntoView({
  behavior: 'smooth'
})

Safari 是唯一不支援 behavior: 'smooth' 的瀏覽器。如需最新資訊,請參閱瀏覽器相容性

實作

既然你知道我如何做到,你會怎麼做呢?讓我們多方嘗試,瞭解在網路上建構應用程式的所有方式。建立 Glitch,並在推特上傳你的版本,我會將其加入下方的「社群混音」專區。

社群重混作品