初期レンダリングのスクロール ターゲットを設定する

CSS プロパティ scroll-initial-target は、コンテナがレンダリングされるとすぐに、特定の子孫要素をスクロール コンテナの表示領域に表示する、宣言型の CSS のみの方法を提供します。以前は、デベロッパーは JavaScript(Element.scrollIntoView())または URL フラグメント識別子(#item-id)に依存していましたが、どちらも制限があり、実装が複雑でした。

実装方法

これを適切に実装するには、次の手順を行います。

  1. スクロール コンテナを確保する: ターゲット要素は、スクロール コンテナ(overflow: auto など、スクロールを可能にするオーバーフローがある要素)内にある必要があります。これは、ルート <html> 要素を含む任意の祖先要素にすることができます。
  2. アイテムをターゲットにする: 表示する特定の子孫要素に scroll-initial-target: nearest を適用します。

コードの例: 縦向きのメディア フィード

この例では、フィードはリストの最上部ではなく、特定の「おすすめ」アイテムまでスクロールされた状態で開始されます。

/** 
 * TARGET: The item that should be visible on initial load.
 */
.item.target {
  scroll-initial-target: nearest;
}

戦略的な実装とベスト プラクティス

  • 推奨: scroll-initial-target は、今日から始まるカレンダーや、特定の画像から始まるギャラリーなど、「途中から始まる」エクスペリエンスに使用します。
  • ユーザー補助フォーカスと混同しないでください。このプロパティは、ビジュアル ビューポートのみを移動します。キーボード フォーカスは移動しません。ターゲットがキーボード ユーザーの開始点となる場合は、element.focus() を手動で管理する必要があります。
  • 読み込み時にスムーズな「スクロール」アニメーションが必要な場合は、使用しないでください。このプロパティは離散的であり、レイアウト フェーズ中に位置を即座に設定します。
  • 同じスクロール可能なコンテナ内の複数の要素に scroll-initial-target を設定しないでください。複数の要素で scroll-initial-target: nearest が指定されている場合、ブラウザは DOM ツリーの順序で最初に表示される要素を選択します。
  • メディアのサイズを指定する。スクロール位置は初期レイアウト時に計算されるため、メディアの読み込み後にターゲットが移動しないように、画像や動画に aspect-ratio または固定の height / width を設定してください。
  • 優先順位を考慮する: URL フラグメント(例: example.com/#top)とコンテナレベルの scroll-start プロパティは、どちらも scroll-initial-target よりも優先されます。

代替戦略

API をまだサポートしていないブラウザでは、JavaScript のフォールバックを使用します。DOMContentLoaded イベントを使用すると、HTML の解析が完了するとすぐにブラウザが要素をスクロールして表示するため、すべての画像とリソースの読み込みを待つよりも高速なエクスペリエンスを提供できます。または、<body> 要素の末尾にスクリプトを配置することもできます。この場合、イベント リスナーは必要ありません。

/**
 * Progressive Enhancement Fallback
 */
document.addEventListener("DOMContentLoaded", () => {
  // Check for native CSS support
  if (!CSS.supports("scroll-initial-target", "nearest")) {
    const feedTarget = document.querySelector(".item.target");
    if (feedTarget) {
      // 'block: center' ensures the featured media is centered in view
      feedTarget.scrollIntoView({ behavior: "instant", block: "center" });
    }
  }
});