はじめに
Web開発において、ツールチップ、ポップオーバー、ドロップダウンメニュー、ホバーカードなどの「ある特定の要素(アンカー)の近くに追従して表示されるフローティング要素」の実装は、長年の課題でした。
これまでは、スクロールやウィンドウサイズ変更に追従させるため、JavaScriptで要素の座標(getBoundingClientRect())をリアルタイムに計算し、インラインスタイルを書き換える手法が一般的でした(Popper.jsやFloating UIなどのライブラリがその代表例です)。しかし、この手法はメインスレッドでJavaScriptが頻繁に実行されるため、特に低スペックデバイスやスクロール時に描画パフォーマンスの低下(ジャンク)を引き起こす原因になっていました。
これらの問題をブラウザのネイティブ機能のみで解決する新しい仕様が CSS Anchor Positioning API です。本記事では、この注目の新機能の基礎から、実用的な実装レシピまでを分かりやすく解説します。
1. CSS Anchor Positioning とは?
CSS Anchor Positioning は、ある要素(アンカー要素)の位置を基準にして、別の絶対配置要素(ターゲット要素 / フローティング要素)の位置を指定・固定するためのCSS標準機能です。
主なメリット
- JavaScript不要: 座標計算やスクロールイベントの監視のためのJSコードが一切不要になります。
- 圧倒的なパフォーマンス: 位置計算と描画がブラウザのレンダリングエンジン側でネイティブに行われるため、スクロール時も滑らかに描画されます。
- HTML構造からの自由: ターゲット要素の
position: absoluteまたはposition: fixedの挙動が強化され、親要素のposition: relativeやoverflow: hiddenのクリッピング制約を受けにくくなります(※特にHTMLの<dialog>やpopover属性と組み合わせた際に効果を発揮します)。
2. 最もシンプルな基本の実装
CSS Anchor Positioning を利用するための基本的なアプローチを順を追って見ていきましょう。
HTMLの構造
アンカーとなるボタンと、そこに紐づくツールチップ(ターゲット)を用意します。
<button class="my-anchor">ここホバーしてね</button>
<div class="my-tooltip">これがツールチップです</div>
CSSの実装
CSSでは、大きく分けて以下のステップで関連付けを行います。
- アンカー要素に
anchor-nameを定義する。 - ターゲット要素に
position: absoluteを指定し、position-anchorで対象を指定する。 anchor()関数を使用して、位置を紐付ける。
/* 1. アンカー要素の設定 */
.my-anchor {
/* アンカー名にはダッシュ(--)から始まるカスタムプロパティに似た識別子を使います */
anchor-name: --anchor-button;
}
/* 2 & 3. ターゲット要素の設定 */
.my-tooltip {
position: absolute;
position-anchor: --anchor-button;
/* アンカーの下端(bottom)にツールチップの上端(top)を合わせる */
top: anchor(bottom);
/* アンカーの水平方向の中央(center)にツールチップの水平中央を合わせる */
left: anchor(center);
transform: translateX(-50%);
/* 装飾 */
background: #333;
color: #fff;
padding: 8px;
border-radius: 4px;
}
たったこれだけの記述で、ボタンの直下にピッタリと張り付くツールチップが完成します。画面をスクロールしても、ブラウザが自動的に位置を追従させてくれます。
3. 実践テクニック:自動位置調整(position-try)
ツールチップなどのフローティング要素で最も厄介なのが、**「画面端で要素が見切れてしまう問題」**です。例えば、ボタンが画面の一番下にある場合、ツールチップを「下」に表示しようとすると画面外にはみ出してしまいます。
CSS Anchor Positioning は、この「画面外へのはみ出し対策」もCSS側で自動調整する仕組みを備えています。それが position-try-fallbacks です。
.my-tooltip {
position: absolute;
position-anchor: --anchor-button;
/* デフォルトの位置:アンカーの下側 */
top: anchor(bottom);
left: anchor(center);
transform: translateX(-50%);
/* はみ出す場合の代替候補リストを指定 */
position-try-fallbacks: flip-block, flip-inline;
}
flip-block: 上下にスペースがない場合、自動的に上下を反転させます(下がなければ上に表示)。flip-inline: 左右にスペースがない場合、自動的に左右を反転させます。
さらに、カスタムの配置ルールを @position-try ルールを使って詳細に定義することも可能です。
@position-try --top-layout {
bottom: anchor(top);
top: auto;
left: anchor(center);
}
4. Popover API との親和性
CSS Anchor Positioning は、HTML5の標準機能である Popover API(popover 属性) と組み合わせることで、真の力を発揮します。
Popover API を使うと、JavaScriptなしで要素を最前面(トップレイヤー)にポップアップさせることができます。しかし、トップレイヤーに送られた要素は通常のドキュメントフローから完全に離脱するため、これまではアンカーのすぐ隣に配置することが困難でした。
Anchor Positioning はこの問題を解決します。
<!-- Popover API と Anchor の連携 -->
<button class="menu-btn" popovertarget="my-menu" style="anchor-name: --menu-anchor;">
メニューを開く
</button>
<div popover id="my-menu" style="
position: absolute;
position-anchor: --menu-anchor;
top: anchor(bottom);
left: anchor(left);
margin: 0;
">
<ul>
<li>マイページ</li>
<li>設定</li>
<li>ログアウト</li>
</ul>
</div>
この組み合わせにより、「オーバーフローを無視して常に最前面に表示され、かつボタンの直下に完璧に追従するドロップダウンメニュー」 が、一切のJSライブラリなしで実現します。
まとめとブラウザ対応状況
CSS Anchor Positioning は、モダンブラウザ(Chrome, Edge, Operaなど)において標準搭載が進んでいます。FirefoxやSafariにおいても仕様の検討および実装が進められており、近い将来すべての環境でネイティブに動作するようになると期待されています。
現在動作しない環境向けには、公式のポリフィル(CSS Anchor Positioning Polyfill)が存在するため、それらを導入することでプロダクション環境での先行利用も十分に可能です。
無駄なJavaScriptコードを削り、WebサイトのパフォーマンスとUXを劇的に向上させるこの仕様を、ぜひご自身のスタイルシート設計に取り入れてみてください。
