Featured image of post CSS Popover API:JavaScript不要のネイティブオーバーレイ Featured image of post CSS Popover API:JavaScript不要のネイティブオーバーレイ

CSS Popover API:JavaScript不要のネイティブオーバーレイ

CSS Popover APIを使ったネイティブオーバーレイを解説。popover属性、popovertarget、アンカー配置、ライトディスミス、アクセシビリティ、dialog要素やカスタムモーダルとの比較まで。

はじめに

ツールチップやドロップダウンメニュー、モーダルといったオーバーレイUIを構築するには、これまで多くのJavaScriptが必要でした。CSSの position: absolute による手動座標計算、ARIA属性を使ったアクセシビリティ対応、ReactポータルやFloating UIなどのフレームワーク依存の解決策——これらすべてに学習コストとメンテナンスの負荷が伴います。

CSS Popover APIは、宣言的なHTML属性のみでオーバーレイを実現するネイティブソリューションです。表示/非表示の切り替え、ライトディスミス、フォーカス管理、アクセシビリティをネイティブに処理し、多くのケースでJavaScriptを不要にします。


1. 基本:popover属性とpopovertarget

Popover APIの核となるのは2つのHTML属性です。popover 属性で要素をポップオーバーとしてマークし、popovertarget 属性でトリガーボタンと紐付けます。

<button popovertarget="my-popover">メニューを開く</button>
<div id="my-popover" popover>
  <p>このコンテンツがネイティブポップオーバーで表示されます。</p>
</div>

ボタンをクリックするだけでポップオーバーの表示が切り替わります。popover 属性には2つのモードがあります。

モード動作使用例
popover="auto"外側クリックまたはEscapeで閉じる。同時に1つのみ表示可能ツールチップ、ドロップダウンメニュー
popover="manual"プログラム的にのみ閉じる。複数同時表示可能トースト通知、スライドパネル

2. Popover Toggle API

プログラムからポップオーバーを制御する場合、HTMLElement に3つのメソッドが用意されています。

const popover = document.getElementById('my-popover');
popover.showPopover();  // 表示
popover.hidePopover();  // 非表示
popover.togglePopover(); // 切り替え

beforetoggle イベントと toggle イベントも利用可能です。beforetoggle は可視性が変更される直前に発火し、oldStatenewState プロパティを持ちます。動的なコンテンツの取得やアニメーションの事前準備に活用できます。

popover.addEventListener('beforetoggle', (event) => {
  if (event.newState === 'open') {
    console.log('ポップオーバーが開こうとしています');
  }
});

3. ライトディスミス動作

autoモードのポップオーバーは、以下のタイミングで自動的に閉じます。

  • ポップオーバー外をクリックしたとき
  • Escapeキーを押したとき
  • 別のautoポップオーバーが開かれたとき

この動作は <dialog> と同じclose-watcher基盤によって制御されています。manualモードでは明示的な閉操作が必要なため、ユーザーがアクションを完了するまでオーバーレイを表示し続けたい場合に適しています。

<button popovertarget="toast" popovertargetaction="show">トースト表示</button>
<div id="toast" popover="manual">処理が完了しました</div>

popovertargetaction 属性で "show""hide"、デフォルトの "toggle" を指定できます。


4. アンカー配置(Anchor Positioning)

Popover APIはCSS Anchor Positioning APIと統合されており、Popper.jsやFloating UIなしで宣言的な位置決めが可能です。

.popover {
  position-anchor: --trigger;
  inset-area: block-end;
}
<button id="trigger" popovertarget="tooltip">マウスを重ねてください</button>
<div id="tooltip" popover class="popover" anchor="trigger">ツールチップ内容</div>

anchor 属性でトリガー要素を指定し、inset-areaposition-fallback で表示位置を制御します。ビューポートにはみ出す場合は自動的に反対側に反転するため、従来JavaScriptで行っていた位置調整が不要になります。


5. スタイリングとアニメーション

ポップオーバーはトップレイヤーに描画されるため、z-indexのスタックコンテキスト管理から解放されます。::backdrop 疑似要素で背後をスタイリングできます。

[popover]::backdrop {
  background: rgba(0, 0, 0, 0.3);
}

[popover]:popover-open 疑似クラスで表示時のスタイルを指定します。ただし、ポップオーバーは display: nonedisplay: block の切り替えで動作するため、CSSトランジションを直接適用できません。@starting-styleoverlay プロパティを使った回避策が必要です。

@starting-style {
  [popover]:popover-open {
    opacity: 0;
    translate: 0 -10px;
  }
}
[popover]:popover-open {
  opacity: 1;
  translate: 0 0;
  transition: opacity 0.3s, translate 0.3s, overlay 0.3s allow-discrete;
}

6. アクセシビリティ

Popover APIは多くのアクセシビリティ処理を自動化します。コンテキストに応じて適切な暗黙的ロール(group または dialog)を割り当て、開封時にフォーカスを移動し、autoモードではフォーカスをトラップします。Escapeキー処理も自動です。

追加のARIA属性でさらに使いやすくなります。

<button popovertarget="help" aria-describedby="help">ヘルプ</button>
<div id="help" popover role="tooltip">Escapeキーで閉じます。</div>

メニューとして機能するポップオーバーには role="menu"aria-activedescendant を設定します。スクリーンリーダー(NVDA、VoiceOver、JAWS)でのテストを推奨します。


7. Popover vs. <dialog> vs. カスタムモーダル

機能Popover API<dialog>カスタムモーダル
ライトディスミスビルトイン(auto)手動実装手動実装
トップレイヤー対応showModal() で対応要ポータルまたはz-index
開封にJSが必要不要必要必要
フォーカストラップautoポップオーバーモーダルダイアログカスタム実装
最適な用途ツールチップ、メニュー、トースト確認ダイアログ、フォームフレームワーク管理の複雑なオーバーレイ

確認ダイアログやフォームのようなフォーカストラップが必要なケースでは <dialog> を、軽量な非モーダルオーバーレイにはPopover APIを使用します。


8. ブラウザサポートとPolyfill

Chrome 114+、Edge 114+、Firefox 125+、Safari 17+ でサポートされています。フィーチャーディテクションは以下の方法で行えます。

if (typeof HTMLElement.prototype.showPopover === 'function') {
  // Popover APIに対応
}

非対応ブラウザには @oddbird/popover-polyfill が利用可能です。ただし ::backdrop やトップレイヤーの動作を完全に再現できるわけではなく、position: fixed によるフォールバックとなります。


まとめ

CSS Popover APIは、宣言的なUI開発における重要な進歩です。表示/非表示の切り替え、ライトディスミス、フォーカス管理、位置決めをネイティブに処理することで、多くのオーバーレイユースケースからJavaScriptを排除できます。CSS Anchor Positioningと組み合わせれば、ツールチップ、ドロップダウンメニュー、トースト通知、コンテキストメニューを数行のコードで実装できます。

複数ステップのモーダルやフレームワーク管理が必要な複雑なケースでは従来のJavaScriptソリューションが引き続き有効ですが、日常的なオーバーレイパターンの大部分において、Popover APIはよりシンプルでアクセシブル、かつパフォーマンスの高い選択肢です。