スケートボードでトリックを決めるとき、足元の板と体の動きが完全に連動していないと成立しない。Webのスクロール体験にも同じことが言える。ユーザーの指の動き(スクロール)と画面の応答が噛み合って初めて、直感的な操作感が生まれる。

京谷商会のトップページには18の専門ポータルが並んでいて、それぞれのセクションに色付きのバーがある。このバーが画面上端に達すると、そのままヘッダーとして固定される。次のバーが来れば、前のバーを押し出して入れ替わる。やっていることはシンプルだけど、ユーザーに「今どこにいるか」を常に伝えるUIとして、かなり効いている。

以下のデモでは、実際にスクロールしてバーの入れ替わりを体感できる。各セクションのカラーバーが画面上端で固定され、次のバーが到達すると押し出されて入れ替わる動作を確認してほしい。

スティッキーセクションバーの動作デモ。iframe内でスクロールしてバーの入れ替わりを体感できる。

position: sticky だけで成立する仕組み

正直に言うと、最初はJavaScriptでスクロール位置を監視して切り替える方向で考えていた。でも実際にやってみたら、CSSの position: sticky; top: 0 だけで全部解決した。

stickyの優れているところは、親要素の範囲内でのみ固定されるという制約にある。セクションバーに sticky を指定すると、そのセクションが画面内にある間だけバーが上端に留まって、セクションがスクロールアウトすれば一緒に消える。JavaScriptゼロで「入れ替え」が成立する。CSS-Tricksのsticky解説を読んだときに「これだ」と思った。

ただしハマりポイントがある。祖先要素に overflow: hidden がかかっていると、stickyが効かなくなる。コーヒーの焙煎で温度管理を怠ると全部台無しになるのと同じで、CSSの基盤部分の設計がずれていると上に何を積んでもうまくいかない。

z-indexのレイヤーマップ

このUIで一番神経を使ったのがレイヤーの重なり順だ。3つの要素が独立した固定位置を持つため、z-indexの設計を間違えると見た目が破綻する。

僕らが採用したのはこういうレイヤーマップになる。最下層にヘッダー(z-index: 1000)、その上にセクションバー(z-index: 1001)、最上層にナビゲーションメニュー(z-index: 1002)。セクションバーがヘッダーより上にあるのは、バーがヘッダーの上を「滑って」入れ替わる動きを自然に見せるため。ナビは何があっても触れる場所に置きたいから、一番上に独立させた。

下のセクションバーが上のバーを覆い隠す動きは、DOMの描画順序に任せている。MDNのスタッキングコンテキストで解説されている通り、同じz-indexの要素はHTMLの出現順で後のものが手前に描画される。つまりHTMLで後に書かれたセクションが自動的に前のセクションの上に来る。特別な処理は何も書いていない。

ブランドカラーの18色設計

18ポータルそれぞれに固有のブランドカラーが割り当てられていて、セクションバーの背景色になっている。SEOの深い紺、ADSの赤、DEVの緑。色を見るだけでどのポータルかわかるようにしたかった。

ただ18色もあると、明るい色のバーで白文字が読めなくなるケースが出てくる。そこでコントラスト比4.6:1を下回る色は自動的に暗く補正する仕組みを入れた。Material Designのカラーロールで語られる「コンテナカラーとオンカラーの関係」を参考にしている。アクセシビリティとブランドカラーの両立は、妥協ではなく設計の精度で解決する問題だと思う。

ナビゲーションを分離した理由

最初の設計では、セクションバーの中にメニューリンク(サービス・会社概要・お知らせ・お問い合わせ)も入れていた。でもバーが入れ替わるたびにメニューが一瞬ちらつく問題が出て、すぐに別の方法を探した。

結果として、ナビゲーションをセクションバーから完全に分離し、z-index: 1002の独立した固定要素にした。画面右上に常駐しているから、どのセクションを見ていても即座にページ遷移できる。見た目の統合感は少し犠牲になるけど、「いつでもメニューにアクセスできる」というユーザビリティの方が重要だと判断した。3Dモデリングでも、見た目の美しさとメッシュの扱いやすさのどちらを優先するかは常にトレードオフで、機能性を取る場面は多い。

タイルフリップとの連続体験

ページを開くと最初に目に入るのは、河野さんが設計したタイルフリップアニメーションのヒーローだ。世界中の風景写真がタイルの回転で切り替わるあの表現から、スクロールするとカラーバーが次々と入れ替わるスティッキーセクションバーへ。

この2つは別の技術で実装されているけど、訪問者が受け取る体験としては「動きのあるサイト」という一つの印象に統合される。タイルの「回転」とバーの「入れ替わり」。どちらも画面の一部が変化することで文脈の切り替えを伝えるという共通の設計原則に基づいている。

フロントエンドの実装面に興味がある方は、石井が書いたCSS 3D Transformsの実装解説を読んでほしい。perspectivebackface-visibility の具体的なコードレベルの話が丁寧にまとまっている。