ストーリー コンポーネントの作成

ウェブの Instagram ストーリーと同様のエクスペリエンスを構築する方法の基本的な概要。

この投稿では、レスポンシブで、キーボード ナビゲーションをサポートし、ブラウザ間で動作するウェブ向けのストーリー コンポーネントの構築に関する考えを共有します。

デモ

このストーリー コンポーネントを自分で作成する実践的なデモをご希望の場合は、ストーリー コンポーネントの Codelab をご覧ください。

動画をご覧になる場合は、この投稿の YouTube バージョンをご覧ください。

概要

ストーリー UX の一般的な例として、Snapchat ストーリーと Instagram ストーリー(もちろんフリートも)の 2 つがあります。UX の観点では、ストーリーは通常、モバイル専用のタップ中心のパターンで、複数の定期購入を案内します。たとえば Instagram では、ユーザーが友だちのストーリーを開いて写真を閲覧します。一般的にこれほどの人数で同時に行います。デバイスの右側をタップすると、その友だちの次のストーリーにスキップします。右にスワイプすると、ユーザーは別の友だちに移動します。ストーリー コンポーネントはカルーセルとよく似ていますが、単次元の配列ではなく多次元の配列をナビゲートできます。各カルーセルの中にカルーセルがあるようなものです🤯

カードを使用して可視化された多次元配列。左から右に紫色の枠線カードが積み重ねられ、各カードの中には 1 枚以上のシアンの枠線カードが配置されています。リスト型。
1 番目の友人のカルーセル
2 番目のストーリーの「重ねられた」カルーセル
👍? リスト形式(別名: 多次元配列)

ジョブに適したツールの選択

全体として、いくつかの重要なウェブ プラットフォーム機能のおかげで、このコンポーネントはとても簡単に構築できることがわかりました。説明しましょう。

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 DevTools の Device Mode を使用して、グリッドによって作成された列をハイライト表示する

grid レイアウトを細かく見てみましょう。

  • モバイルでは明示的に 100vh100vw でビューポートを埋め、パソコンではサイズを制限します。
  • / によって行テンプレートと列テンプレートが区切られます
  • auto-flowgrid-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;
}
子がスナップ ターゲットにオプトインする。

スクロールのスナップポイントを選んだ理由はいくつかあります。

  • 無料のユーザー補助機能。スクロール スナップ ポイントの仕様では、左矢印キーと右矢印キーを押すと、デフォルトでスナップ ポイント間を移動する必要があると規定されています。
  • 拡大する仕様: Scroll Snap Points の仕様は新機能の追加や改善が継続的に行われています。そのため、私のストーリー コンポーネントは今後改善されるでしょう。
  • 実装の容易さ。スクロールのスナップ ポイントは、実際には、タップ中心の水平方向のページ分割のユースケース用に構築されています。
  • フリー プラットフォーム スタイルの慣性。どのプラットフォームも、スクロールと静止のスタイルが正常であるのに対し、正規化された慣性とは対照的に、それぞれのスタイルでスクロールして静止します。

ブラウザ間の互換性

テストは、Opera、Firefox、Safari、Chrome、Android、iOS で実施しました。ここでは、機能とサポートの違いが見られたウェブ機能の概要を簡単に説明します。

ただし、一部の CSS が適用されていないため、現在一部のプラットフォームでは UX の最適化が行われていません。これらの機能を管理する必要がなく、最終的には他のブラウザやプラットフォームにも導入されることを確信しています。

scroll-snap-stop

カルーセルは、CSS の Scroll Snap Points 仕様を作成するきっかけとなった主要な UX ユースケースの 1 つです。ストーリーとは異なり、カルーセルはユーザーが操作した後に必ずしも各画像で停止する必要はありません。カルーセルをすばやく切り替えてもかまいません。一方、ストーリーは 1 つずつ移動するのが最適です。これが、scroll-snap-stop が提供するものです。

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

この記事の執筆時点では、scroll-snap-stop は Chromium ベースのブラウザでのみサポートされています。更新については、ブラウザの互換性をご覧ください。ただし、これは阻害要因ではありません。サポートされていないブラウザでは ユーザーが誤って友だちをスキップしてしまう可能性がありますそのため、ユーザーはより慎重になるか、スキップされた友だちが閲覧済みとしてマークされないように JavaScript を記述する必要があります。

興味があれば、仕様をご覧ください。

overscroll-behavior

モーダルをスクロールしているとき、突然モーダルの背後にあるコンテンツのスクロールが始まったことはありませんか?overscroll-behavior を使用すると、デベロッパーはスクロールをトラップして、スクロールを離れないようにできます。どんなシチュエーションにもぴったりです。マイ ストーリー コンポーネントは、追加のスワイプやスクロール操作がコンポーネントから離れるのを防ぐために、これを使用します。

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

Safari と Opera はこれをサポートしなかった 2 つのブラウザで、まったく問題ありません。これまでと同じようにオーバースクロールできるようになり、この機能強化には気付かないかもしれません。私個人は大ファンで オーバースクロール機能のほとんどに取り入れていますこれは UX の改善につながる恐れのある無害な追加です。

scrollIntoView({behavior: 'smooth'})

ユーザーがタップまたはクリックして友だちのストーリー セットの最後に達したら、スクロール スナップ ポイント セット内の次の友だちに移動します。JavaScript では、次の友だちを参照し、それをスクロールするようにリクエストすることができました。基本的なサポートは素晴らしく、どのブラウザもスクロールで表示しています。しかし、'smooth'、すべてのブラウザがそれに対応しているわけではありません。これは単にスナップされるのではなく、ビューにスクロールされることを意味します。

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

Safari がここで behavior: 'smooth' をサポートしなかった唯一のブラウザでした。更新については、ブラウザの互換性をご覧ください。

ハンズオン

さて、やったらどうやってやったの?多様なアプローチとウェブでの構築方法を 学んでいきましょうGlitch を作成して、そのバージョンをツイートしてください。下のコミュニティ リミックス セクションに追加します。

コミュニティのリミックス