打造精選故事元件

從基礎開始,瞭解如何在網路上建構類似 Instagram 限時動態的體驗。

在這篇文章中,我想分享如何為網頁建構回應式 Stories 元件,支援鍵盤導覽,且可在各種瀏覽器上運作。

示範

如要親自建構這個 Stories 元件,請參閱這個程式碼研究室

如果比較喜歡看影片,可以觀看這篇貼文的 YouTube 版本:

總覽

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

以資訊卡呈現多維陣列。從左到右是一疊紫色邊框的卡片,每張卡片內有 1 到多張青色邊框的卡片。清單中的清單。
第一個好友輪轉介面
第二個「堆疊」的動態消息輪轉介面
👍 清單中的清單,又稱多維陣列

選擇適合的工具

總而言之,由於有幾項重要的網頁平台功能,我發現這個元件的建構過程相當簡單。我們來看看吧!

CSS 格線

結果發現,CSS 格線對於我們的版面配置來說並非難事,因為它具備一些強大的內容管理方式。

好友版面配置

我們的主要 .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 Stories 和 Instagram Stories 為例,每一欄都是好友的故事。我們希望朋友的限時動態繼續顯示在可視區域外,方便使用者捲動瀏覽。格線會為每個好友動態建立 HTML 版面配置所需的欄數,為我們建立動態回應式捲動容器。Grid 讓我們集中處理所有效果。

堆疊

我們需要每位好友的故事,且這些故事必須處於可分頁的狀態。為了準備製作動畫和其他有趣的圖案,我選擇了堆疊。 我說的堆疊是指從上往下看三明治,而不是從側面看。

使用 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;
}
孩子選擇成為快照目標。

我選擇捲動快照點的原因如下:

  • 免費無障礙功能。根據捲動貼齊點規格,按下向左鍵向右鍵時,預設應會移動至貼齊點。
  • 規格不斷成長。捲動快照點規格會持續推出新功能並改善各項設計,這表示我的 Stories 元件只會越來越好用。
  • 導入難易度:捲動快照點實際上是為以觸控為主的水平分頁用途而建構。
  • 免費平台風格慣性。每個平台都會以自己的樣式捲動和停止,而不是以標準化慣性捲動和停止,後者可能會產生詭異的捲動和停止樣式。

跨瀏覽器相容性

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

不過,我們有些 CSS 未套用,因此部分平台目前缺少 UX 最佳化功能。我很高興不必管理這些功能,而且相信這些功能最終會支援其他瀏覽器和平台。

scroll-snap-stop

輪轉介面是促成建立 CSS 捲動快照點規格的主要 UX 用途之一。與「故事」不同,輪轉介面不一定需要在使用者互動後停止顯示每張圖片。快速瀏覽輪轉介面可能沒問題,甚至受到鼓勵。另一方面,最好逐一瀏覽動態消息,而這正是 scroll-snap-stop 的功能。

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

撰寫本文時,只有以 Chromium 為基礎的瀏覽器支援 scroll-snap-stop。如需最新資訊,請參閱「瀏覽器相容性」。但這並非阻礙。這只是表示在不支援的瀏覽器上,使用者可能會不小心略過好友。因此使用者只需更加小心,或者我們需要編寫 JavaScript,確保略過的朋友不會標示為已查看。

如有興趣,請參閱規格

overscroll-behavior

您是否曾捲動對話方塊時,突然開始捲動對話方塊後方的內容?overscroll-behavior 可讓開發人員擷取捲動動作,且永遠不會放開。適合各種場合。「我的故事」元件會使用這項屬性,防止額外的滑動和捲動手勢離開元件。

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

Safari 和 Opera 是不支援這項功能的 2 個瀏覽器,這完全沒問題。這些使用者會獲得他們習慣的過度捲動體驗,可能永遠不會注意到這項強化功能。我個人非常喜歡這項功能,幾乎每次實作過度捲動功能時都會加入。這項新增內容不會造成任何損害,只會提升使用者體驗。

scrollIntoView({behavior: 'smooth'})

使用者輕觸或點按並看完好友的一系列限時動態後,系統就會將他們帶到捲動吸附點集合中的下一個好友。我們可以使用 JavaScript 參照下一個朋友,並要求將其捲動到檢視畫面中。這項功能的基礎支援非常完善,所有瀏覽器都會將其捲動至檢視畫面。但並非所有瀏覽器都這麼做 'smooth'。這只是表示該項目已捲動至檢視畫面,而非貼齊。

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

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

實作

現在您已瞭解我的做法,您會怎麼做呢?讓我們多元化地運用各種方法,瞭解在網路上建構內容的所有方式。建立 Glitch在推文中提及我,我會將你的版本新增至下方的「社群混音」部分。

社群重混作品