スティッキー&フローティングUIシステム は何をしますか?
目的
スティッキー&フローティングUIシステムは、持続的でビューポートに固定された、スクロールに応答するインターフェースコンポーネントを設計するための方法論を提供します。主要なナビゲーション、コンバージョンを促進するCTA(コールトゥアクション)、コンテキストに応じたユーティリティウィジェット、クイックアクションボタンなどの重要なコントロールが、アクティブなスクロール状態でも容易にアクセスできるようにします。
適切に設計されたスティッキー&フローティングシステムは、即時のアクション提供とプライマリコンテンツの消費という空間的な緊張関係を解決します。レイアウトの疲労を防ぎ、ビューポートを過度な視覚的乱雑さから保護し、モバイルデバイスの物理的なセーフエリア(デバイスのノッチやシステムホームインジケーターなど)を尊重し、キーボードフォーカスの隠蔽障害(WCAG 2.2 SC 2.4.11)を厳格に軽減します。
ユースケース
- プログレッシブナビゲーションヘッダー: スクロールダウンで非表示になり(読み取り領域を最大化)、スクロールアップで表示されるヘッダー(ナビゲーションをすぐに利用可能にする)。
- モバイル用持続的ボトムドック: モバイルレイアウト向けに、主要なコンバージョンアクション(「カートに追加」「今すぐ予約」「申し込む」など)を含む、ビューポート下部に固定またはドッキングされたバー。
- スティッキーサイドバーウィジェット: コンテキストに応じたサブナビゲーション、共有バー、商品購入設定などを、メインコンテンツエリアと一緒にスクロールさせつつ、構造的な境界に達する前に固定する。
- フローティングアクションボタン(FAB): 「トップに戻る」ナビゲーション、直接サポートチャット、カートドロワーなど、高頻度アクションのためのビューポートアンカー型トリガー。
- アンカーとリーディングプログレスバー: ビューポートの完了率を追跡したり、ページ本文のサブセクションへの直接リンクを提供するスティッキー要素。
使用すべきでない場合
- データ密度の高いSaaSダッシュボード: 表形式データ、作業キャンバス、ビューポート固定パネルによって画面スペースが厳しく制約されている場合。代わりに
dashboard-layout-systemを使用してください。 - 短い/単一ビューポートのページ: ページ全体のコンテンツが単一の画面ビューに収まり、スクロールせずにアクセスできる場合。
- ナラティブ駆動型の実験的サイト: 標準的なナビゲーションのユーティリティよりも、意図的な視覚的混乱や没入型3D空間フローが選択されている場合。
- キーボードフォーカスが多いフォーム: 多くのフィールドを持つフォームにスティッキーボタンを配置し、モバイルの仮想キーボード上でアクティブな入力フィールドを覆ってしまう場合。
入力
- コンテンツとナラティブ構造: ページのワイヤーフレームシーケンス(
section-composition-systemから)。いつ、どこでスティッキー要素をアクティブにするかを理解するため。 - デバイスのビューポート制約: モバイル、タブレット、デスクトップのターゲットブレークポイント。ドッキングバーとフローティングサイドコンテナーのレイアウトを適応させるため。
- プライマリおよびセカンダリCTA: 持続的な可視性を必要とするコンバージョン目標の特定。
- Zインデックス積層戦略:
elevation-and-depth-systemで確立された積層関係と階層。視覚的な重なり競合を防ぐため。 - システムセーフエリアメトリクス: デバイスのクロームオーバーラップを防ぐために必要なハードウェアセーフエリアインセット(
env(safe-area-inset-bottom)、ノッチ)。
出力
- スティッキー動作仕様: スクロールトリガー、アニメーション閾値、エントリー/イグジット遷移式の明示的な定義。
- モバイルボトムドックレイアウト: モバイル画面向けに空間最適化されたレイアウト設計図。ターゲットサイズ、セーフエリアオフセット、コントラスト要件を詳細に示す。
- 隠蔽防止マップ: スティッキーオーバーレイがフォーカスされた要素をブロックしないようにするための設計定義(WCAG 2.2 SC 2.4.11)。
- デスクトップサイドバー/ウィジェット固定仕様: スクロールするサイド要素がスナップインして固定される境界ルール(ヘッダー、フッター、セクション終了点)。
ワークフロー
1. ビューポートゾーニングと空間予算の確立
持続的なレイヤーを配置する前に、「視覚的な安全ゾーン」を定義し、コンテンツの可読性が保たれるようにします。
- 15%予算ルール: スティッキー要素は、どのデバイス画面でも垂直ビューポート全体の15%を超えて消費してはなりません。
- Zインデックス割り当て:
elevation-and-depth-systemの階層を使用して、明確なスタッキング値を割り当てます。- プログレッシブヘッダー:
z-index: 100(レベル3: スティッキー) - モバイルボトムドック:
z-index: 150(レベル3: スティッキー/フローティング) - フローティングアクションボタン:
z-index: 200(レベル3: フローティングトリガー)
- プログレッシブヘッダー:
- スタックオーバーラップの回避: スティッキーヘッダーとスティッキーボトムバーが画面を圧迫する場合、両方を同時に静的状態にしないでください。十分な余裕を持たせるか、特定の状態で非表示にしてください。
2. プログレッシブヘッダーの動作設計
静的なスティッキーヘッダーは、貴重な垂直ピクセルを占有します。「プログレッシブ」モデルを実装します:
- デフォルト状態: ページの背景に合わせた透明または統合されたヘッダー。
- スクロールダウン (閾値 >100px): ヘッダーをスムーズに上に翻訳して非表示にします (
transform: translateY(-100%))。コンテンツのスキャン領域を最大化するため。 - スクロールアップ (デルタ >15px): ヘッダーを即座に、またはスムーズにビューに戻します。ソリッドまたはぼかしたサーフェス背景 (
backdrop-filter: blur(8px)) を適用し、微妙なシャドウを追加してページ本文のテキストとの分離を示します。 - 境界停止: スクロールバーがビューポートの先頭に戻ったとき (scrollY < 50px)、スクロールアップ遷移を無効にし、ヘッダーを元の静的なレイアウトに戻します。
3. モバイル持続的ボトムドックの設計
ボトム持続バーはモバイルコンバージョンの主要な推進力ですが、物理的および視覚的な干渉を非常に受けやすいです。
- 物理的セーフエリア: CSS環境変数を使用して、常にドックの下端をアンカーします:
padding-bottom: calc(var(--base-padding) + env(safe-area-inset-bottom))。これにより、インタラクティブなトリガーと重なることなく、iOSホームインジケーターやAndroidナビゲーションバーの上にきれいに配置されます。 - エントリースクロールトリガー: 初期のヒーロービューポートではモバイルボトムドックを表示しません。ユーザーがヒーローセクションのインラインCTAをスクロールして通過した後 (閾値 > 100% VH) に、ドックを下からスライドアップさせます (
transform: translateY(0)をtranslateY(100%)から)。 - レイアウト分割: タップターゲットを非常にクリーンに保つため、ドックは単一のプライマリアクションボタン (例:「カートに追加」) と1つのセカンダリユーティリティボタン/バッジ (例:「価格」または「保存」) に制限します。
4. デスクトップスティッキーサイドバーとウィジェットの構造化
サイドバーウィジェットは、深いメインコンテンツ列と一緒にスクロールしながら、ビューポートフォーカスに固定されたままである必要があります:
- コンテナー分離: サイドバーは、メインコンテンツエリアと同じ高さの列コンテナー内に存在する必要があります。
- 位置スティッキー仕様: ウィジェットを
position: sticky; top: calc(var(--header-height) + var(--space-l));でスタイリングします。これにより、ウィジェットがメインナビゲーションバーの後ろに滑り込んだり、重なったりするのを防ぎます。 - フッター境界ロック: スティッキーウィジェットの親列が
overflow: visibleであること (またはGridフレックスラッパー内に適切に含まれていること) を確認し、ブラウザがウィジェットをグローバルフッターや下部セクションと重ならないように自然に停止できるようにします。
5. キーボードフォーカスの隠蔽防止 (アクセシビリティの中核)
最も頻繁に発生するウェブデザインのアクセシビリティ障害の1つは、キーボードタブユーザーがリンクにフォーカスしたときに、そのリンクがスティッキーヘッダーやボトムドックの下に隠れてしまうことです (WCAG 2.2 SC 2.4.11 フォーカスが隠れないこと に違反)。
- スクロールマージントップ: すべてのターゲットセクション、見出し (
h2、h3)、および主要なインタラクティブターゲットにグローバルなscroll-margin-topを適用します::target, [id] { scroll-margin-top: calc(var(--header-height) + var(--space-m)); } - フォーカスパディング: インタラクティブ要素がキーボードフォーカスを受け取った場合、ブラウザビューは要素が永続的なスティッキーオーバーレイの境界の外側で完全に表示されるようにスクロールする必要があります。
- 避難口: スティッキー要素からモーダルやドロップダウンが開かれた場合、フォーカスをトラップし (
focus-trap-implementationを使用)、背景のページコンテンツをinertにします。
6. フローティングアクションボタン(FAB)とトップに戻るトリガーの設計
FABはビューポートの下隅に配置され、迅速なセカンダリグローバルユーティリティを提供します。
- 閾値ベースのエントリー: ユーザーが少なくとも2つの完全なビューポートをスクロールするまで (scrollY > 200% VH)、「トップに戻る」トリガーを非表示にします。トリガーされたら、フェードインおよびスケールインします (
transform: scale(1); opacity: 1;をscale(0.8); opacity: 0;から)。 - ビューポートオフセット: デスクトップではFABをビューポートの右端から少なくとも
24px、モバイルでは16px離して配置します。 - ターゲットブロッキングの回避: FABをプライマリコンテンツの読み取りラインと水平方向に反対側に配置します。ページ下部にスクロールしたとき、リンク、ソーシャルアイコン、またはインラインナビゲーションをブロックしないようにします。
決定ルール
- 静的 vs. プログレッシブヘッダー: サイトがタスク重視のウェブポータルやEコマースショップであり、検索やフィルタリングが常に使用される場合は、静的スティッキーヘッダー を使用します。記事レイアウト、コンテンツマーケティング、セールスランディングページなど、垂直方向の読み取り領域が優先される場合は、プログレッシブスティッキーヘッダー を使用します。
- ボトムドック vs. インラインCTA: モバイルでは、ページに単一の高価値コンバージョン目標(サインアップや購入など)が含まれている場合は、ボトムドックCTA を使用します。ページに同じ優先度の競合するアクションが複数ある場合は、ボトムドックを使用しないでください。
- FABのサイズとタッチエリア: フローティングトリガーは、円形または角丸のカードにします。視覚要素は直径が少なくとも
48px必要であり、実際のインタラクティブなタップコンテナーは、親指でのアクセスを容易にするために、最小フットプリント44x44px(WCAG 2.2推奨) を満たす必要があります。 - プログレッシブブラー vs. ソリッドカラー: 完全に不透明な背景の代わりに、
backdrop-filter: blur(8px)と若干透明な色 (例:rgba(255, 255, 255, 0.8)) を使用します。これにより、視覚的な奥行き感が維持され、ユーザーがスティッキーフレームの背後でスクロールの進行を知覚できるようになります。
制約
- アクセシビリティ (WCAG AA最低限):
- SC 2.4.11 フォーカスが隠れないこと (最低限): 高コントラストのフォーカスリングは、スティッキー要素の後ろに隠れてはなりません。要素がヘッダーやフッターによってブロックされることなく、タブでクリーンに移動できることを確認します。
- SC 2.5.8 ターゲットサイズ (最低限): スティッキーバーやFAB内のすべてのインタラクティブターゲットは、少なくとも 24x24px である必要があり、モバイルボトムドックのプライマリ親指トリガーでは 44x44px が推奨されます。
- タブトラップなし: キーボードユーザーは、標準の
Tab/Shift+Tabを使用して、スティッキーバーコントロールに出入りできる必要があります。
- レスポンシブ性 (レイアウト安定性):
- スティッキーレイヤーは、ビューポートの水平方向のオーバーフローを引き起こしてはなりません。パーセンテージベースの幅または
left: 0; right: 0;レイアウトを、正確なボックスサイズ制約とともに使用します。 - モバイルでは、デスクトップのスティッキーサイドバーを単純なインラインパネルに変換するか、ボトムドロワーにまとめます。
- スティッキーレイヤーは、ビューポートの水平方向のオーバーフローを引き起こしてはなりません。パーセンテージベースの幅または
- レイアウトシフトの軽減 (CLS):
- 元の空間ボリュームを予約せずに、要素を動的に
position: staticからposition: fixedに変更しないでください。fixedに切り替えると、元のコンテナーの高さが即座に collapse し、大きな累積レイアウトシフト (CLS) を引き起こします。代わりに、position: sticky(レイアウトボリュームを予約する) を使用するか、事前に予約されたコンテナー内でスタイルを切り替えます。
- 元の空間ボリュームを予約せずに、要素を動的に
一般的な障害パターン
- フォーカスブロッキングベール: キーボードユーザーがページをタブ移動するが、フォーカスリングがスティッキーヘッダーの下に完全に隠れているリンクに到達し、見えなくなる。
- iOSホームインジケーターの重なり:
env(safe-area-inset-bottom)を追加せずにモバイルボトムバーをドッキングすると、ネイティブOSのスワイプバーが「購入する」ボタンの真上に配置される。 - ジッタースクロールループ: 境界線で正確にトリガーするスクロール遷移をJavaScriptで設定し、スティッキーバーが可視状態と非表示状態の間を急速にちらつく。
- ビューポートサンドイッチ: 小型モバイルデバイスで、厚いスティッキーヘッダーと厚いスティッキーボトムバーが同時にアクティブになり、読み取り可能な画面スペースがわずか40%のウィンドウに減少する。
- CLSスナッピングコラプス: スクロール時にヘッダーを
fixedに切り替えると、メインページコンテンツが即座に80px上にスナップし、ユーザーを混乱させる。
検証基準
- ビューポート面積チェック: スティッキー要素がデスクトップまたはモバイルで垂直ビューポートの15%を超えて占有していないこと。
- フォーカス保護 (SC 2.4.11): キーボードフォーカスされたすべての要素が、永続的なスティッキー要素の境界の外側に完全に表示されていること。グローバルな
scroll-margin-topが設定されていること。 - モバイルセーフエリアの調整: モバイルボトムドックが
env(safe-area-inset-bottom)を明示的に使用して、デバイスコントロールの重なりを防いでいること。 - トリガー閾値ロジック: モバイルボトムドックが初期のヒーロービューポートで非表示のままであり、ヒーローCTAを通過した後でのみフェードイン/スライドインすること。
- レイアウトシフトの防止: プログレッシブヘッダーとスティッキーサイドバーウィジェットが
position: stickyを使用してスタイル設定されているか、事前に測定されたコンテナー内に配置され、累積レイアウトシフト (CLS) がゼロであることが保証されていること。 - 重なり競合なし: スタッキングコンテキストのz-indexが明確にマッピングされ、文書化され、視覚的な重なりエラーを防いでいること。
- ターゲットフットプリント: モバイルドックのトリガーとFABが44x44pxのタッチターゲット推奨を満たしていること。