プロダクトナビゲーションにホバー連動の背景色トランジションを追加
プロダクトナビゲーションバーとドロワーヘッダーに、ホバー操作と連動した背景色のスムーズなトランジションが追加されました。ユーザーが各プロダクトリンクにホバーすると、そのブランドカラーを薄く溶け込ませた背景色にナビゲーション全体が切り替わります。
背景
今回の変更は、11ty.dev のプロダクトナビゲーションの実装を参考に導入されました。PR本文では「Copying the legend, @zachleat and his efforts」と言及されており、同様のインタラクションパターンをWebAwesomeのドキュメントサイトに取り込んだものです。
WebAwesomeのドキュメントサイトは Web Awesome・Font Awesome・Build Awesome という複数プロダクトを横断するナビゲーションを持ちます。各プロダクトにはそれぞれブランドカラー(オレンジ・ブルー・グリーン)が定義されていましたが、これまでナビゲーション背景は静的な --wa-color-surface-lowered で固定されており、ホバー操作に対する視覚的フィードバックがありませんでした。
技術的な変更
変更の中心は utils.css に集約されており、CSS カスタムプロパティと :has() セレクタを組み合わせた状態管理のアプローチが採用されています。
まず、ライトモード・ダークモードそれぞれに対応した「静かな塗りつぶし」カラートークンが追加されました。color-mix(in oklab, ...) を使ってブランドカラーを白または黒と混ぜることで、主張しすぎない淡い背景色を生成しています。
/* ライトモード(white 85% で希釈) */
--nav-products-fill-quiet-web: color-mix(in oklab, var(--brand-web-awesome-orange), white 85%);
--nav-products-fill-quiet-font: color-mix(in oklab, var(--brand-font-awesome-blue), white 85%);
--nav-products-fill-quiet-build: color-mix(in oklab, var(--brand-build-awesome-green), white 85%);
/* ダークモード(black 65% で希釈) */
.wa-dark {
--nav-products-fill-quiet-web: color-mix(in oklab, var(--brand-web-awesome-orange), black 65%);
--nav-products-fill-quiet-font: color-mix(in oklab, var(--brand-font-awesome-blue), black 65%);
--nav-products-fill-quiet-build: color-mix(in oklab, var(--brand-build-awesome-green), black 65%);
}
次に、ホバー状態の検知とCSS変数の切り替えに :has() セレクタが使われています。wa-page をルートとして、内部のプロダクトリンク要素のホバー状態を上位セレクタから参照することで、ナビゲーション全体の背景色を制御します。
wa-page:has(.wrapper-nav-products, .nav-products-drawer) {
&:has(.product-web-awesome:hover) {
--nav-products-bg: var(--nav-products-fill-quiet-web);
}
&:has(.product-font-awesome:hover) {
--nav-products-bg: var(--nav-products-fill-quiet-font);
}
&:has(.product-build-awesome:hover) {
--nav-products-bg: var(--nav-products-fill-quiet-build);
}
}
背景色の適用側では、.wrapper-nav-products と wa-page > [slot='banner'] の両方で background-color がCSS変数 --nav-products-bg を参照するよう変更され、ホバーがない状態ではフォールバック値として従来の --wa-color-surface-lowered が使われます。
/* 変更前 */
background-color: var(--wa-color-surface-lowered);
/* 変更後 */
background-color: var(--nav-products-bg, var(--wa-color-surface-lowered));
transition: background-color var(--wa-transition-slow) var(--wa-transition-easing);
この変更により、ホバー時には --nav-products-bg が上書きされて有効になり、非ホバー時はフォールバックが機能するため、既存の表示に影響を与えません。
設計判断
:has() による「上位要素からの状態参照」 という手法が採用された点が、この変更の設計上の核心です。通常のホバースタイルは対象要素自身や子要素に適用されますが、今回はホバーされた子孫要素の状態を祖先要素のカスタムプロパティに伝播させています。これによって、ナビゲーション背景・バナースロットという複数の要素を単一の状態変数 --nav-products-bg で一元制御できています。
color-mix(in oklab, ...) の混合比率がライト(white 85%)とダーク(black 65%)で非対称になっている点も注目されます。ダークモードで混合量を少なく(35%のブランドカラーを残す)することで、暗い背景上でも色の存在感を保つよう調整されています。
まとめ
CSSカスタムプロパティ・:has() セレクタ・color-mix() というモダンCSS機能を組み合わせることで、JavaScriptを一切使わずにホバー連動の背景色トランジションが実現されています。コンポーネントの実装ではなくドキュメントサイトのスタイリングへの変更ですが、状態のスコープ管理とフォールバック設計のパターンとして参考になる実装です。