🐈

Popover API さわってみた

2023/07/04に公開

Chrome 114からPopover APIがサポートされました。
Popover APIは「トースター」などのコンテンツ上に別のコンテンツを表示しユーザーをサポートするようなコンポーネントをjavascriptを使うことなく実装できる便利な機能です。
基本的な使い方からdialogとの使い分けまで調べたのでまとめたいと思います。

基本的な使い方

Popoverを表示する方法は2つあります。

  1. popover属性とpopovertarget属性を使用する方法

以下のように、ポップオーバーで表示したい要素に対して popoveridを指定、トリガーとする<button>(もしくは<input>)に対して、popovertargetpopoverで指定したid指定します。
これでボタンを押せば表示できます。

<div id="popover" popover>contents</div>
<button popovertarget="popover">toggle Popover</button>
  1. HTMLElement.togglePopover() || showPopover()を使用する方法
# html
<div id="popover" popover>contents</div>

# js
const popover = document.getElementById("popover");
document.addEventListener("keydown", (event) => {
	if (event.key === "j") {
		popover.togglePopover();
    // popover.showPopover()
	}
}); 

HTML属性

popover

popoverを指定された要素は、デフォルトで非表示になり、上記の使い方で挙げた、いずれかの方法で表示することが出来ます。表示された要素は、他の要素よりも上のレイヤーで表示されるためz-indexに左右されることなく表示されます。

このpopoverには automanualを渡すことができ、違いは以下です。

特徴 auto manual
ESCで閉じる できる できない
ポップオーバー外をクリックすると閉じる できる できない
複数のpopover要素を表示 できない できる

popovertarget

<button>(もしくは<input>)に対してpopovertarget="popoverid"のようにpopover要素のidを指定することで、popover要素を制御する要素にすることができます。

popovertargetaction

popovertargetを指定した<button>(もしくは<input>)に対して指定することでpopover要素に対する動作を指定することが出来ます。指定できる値は以下の3つです。

  1. show => popover要素を表示する
  2. hide => popover要素を非表示する
  3. toggle =>popover要素の表示・非表示を切り替える。デフォルトでは、このtoggleになる

CSS

backdrop

擬似要素の ::backdrop を使うことで、popover要素の背景のスタイルを当てることができます。
(背景を暗くしたり、ぼかしたりなど)

popover-open

擬似要素のpopover-openを使うことで、popover要素が表示されている時のみ適用されるスタイルを当てることができます。

基本的な使い方は、こんな感じです。

Popover API と <dialog>

Popover APIを初めて見た時「めっちゃ便利じゃん!」と思った一方で、「<dialog>でも似たようなこと出来るじゃん?」とも思いました。そこで、Popover APIと <dialog>の使い分けを調べてみました。

この2つを使い分ける上で、モーダルとモードレスという概念を理解する必要があると思ったので簡単に説明します。
ソシオメディアさんによると、この2つの説明は以下の通りです。

モーダル

モードがある状態。つまり、システムが特定の機能の使用に制限された状態。ユーザーが自由に操作を行えなくなることと、モード別に機能の意味や振る舞いが変化することから、ユーザーインターフェースのデザインでは、できる限りモードを設けないほうがよいとされる。
https://www.sociomedia.co.jp/1320

モードレス

モードがない状態。ユーザーインターフェースをデザインする際に目指すべき状態。状況に依存した機能制限がなく、自由な手順でタスクを進行することができ、かつ特定の操作がシステムによって常に一定に解釈される状態。
https://www.sociomedia.co.jp/326

簡単にまとめると
モーダルは「モードがある状態」なので、ユーザーに制限がかかります。
反対にモードレスは「モードがない状態」なので、ユーザーは次の動作を自由に決められます。

これを前提とすると、Popover APIと <dialog>の使い分けはシンプルに以下になりそうです。

モーダル ⇒ <dialog>
モードレス ⇒ Popover API

モーダル

<dialog>showModal() を使用することで、以下のようにモーダルで必要な機能がデフォルトで搭載されます。

  1. 開いた時にdialog要素内のフォーカス可能な最初の要素にフォーカスが自動でセット
  2. ESCやdialog要素外のクリックで閉じる
  3. aria-modal=true になり、支援技術にモーダルであることが伝えられる
  4. ::backdrop擬似要素を使用してスタイルを当てられる

Popover APIでもモーダルのようなUIを実装することは可能ですが、↑の1や3はありませんし、モーダルの外が非活性にもなりません(クリックすると閉じますが、非活性にはなってません)

そのためモーダルを実装する時は<dialog>を使うのが適切だと言えそうです。

モードレス

<dialog>show()を使用することで、モードレスなUIを実装することもできます。

以下にPopover APIとモードレスな<dialog>の違いを表形式でまとめました。

特徴 Popover API 非モーダルな <dialog>
トップレベルの表示 はい いいえ
CSSによる表示/非表示のアニメーション サポートされている サポートされていない
表示/非表示のトランジションに必要なJSの依存性 いいえ はい
宣言的なHTMLによる表示/非表示の切り替え サポートされている サポートされていない
発火するイベント 「popovershow」と「popoverhide」が発火する 表示時のイベントはなく、「cancel」と「close」のイベントが発火する
使用する要素の種類 HTML内の最も意味的に関連する要素に適用できる(<dialog popover>など) <dialog>要素にのみ適用可能
ページコンテンツの上に描画されるかどうか はい いいえ
role属性の値 N/A role=dialog

この表は以下を参考にChatGPT大先生に作ってもらいました。
https://open-ui.org/components/popover.research.explainer/#popover-vs-dialog

この表からわかるとおり、Popover APIは、<dialog>を使ってモードレスなUIを実装するよりも多くのことをサポートしてくれていたり、javascriptを使わずに出来ることも多いため、モードレスなUIはPopover APIを使った方が良さそうです。

おわりに

PopoverAPIについて調べたことをまとめてみました。
今回、記事に書いたこと以外にもネストさせて表示させる方法などもあったりして、PopoverAPIは、まだまだサポートされていないブラウザも多いですが、「トースター」「ツールチップ」「アクションメニュー」など多くの場面で使えるので、積極的に使っていきたいです。

参考にさせていただいた記事

株式会社スタメン

Discussion