背景
フロントエンド開発にて度々登場するUIパーツPopover、dialogについて、見た目など結構似ているので、どういった概念の違いがあって、どんな使い分けをするのかが気になったので自分なりに整理してみました。
簡単な使いかた
HTMLの属性としてpopup、タグとしてdialogは存在しています。
それらの簡単な使い方をみていきましょう。
popover
popover はグローバル属性で、要素をポップオーバー要素として示すために使われます。
とあるのでpopover
属性を要素に付与して使用するため、<div popover>
のように任意の要素をpopover
アイテムとして扱うことができる
デモ
以下のように非モーダルをJSの記述抜きで作成することができます。
See the Pen popup by KobayashiMakoto (@kobax) on CodePen.
dialog
過去に記事としてまとめたことがあります。
【HTML】便利そうな dialog 使ってみた感想
dialog は htmlの要素の一つで、以下のように使うことができます。
JSによってモーダルの開閉を制御することになります。
See the Pen Untitled by 小林誠 (@knicisow-the-vuer) on CodePen.
dialog には標準Roleとして、dialogが存在しています。
そのため、<div role="dialog"
のように書くと、支援技術がダイアログとして識別するのに役立ちます。(実際はこれだけでは足りないが、手動でroleを設定できるということ)
両者の区別はどうすればいいのか
使い方の表面を見た限りでは、属性(popover)とHTML要素(dialog)と随分違うはずなのに、機能的にはそこまで違いがないように思いました。
(※ 素人目線での感想です)
これらは一体どうやって区別するのがいいのでしょうか...?
機能的な面で考えた時に以下の記事に興味深いことが書かれていました。
Comparing the Popover API and the element
また、aria-hasPopUp
という属性の観点から分類を考えることができるという記事も面白いです。
Clarifying the Relationship Between Popovers and Dialogs
自分なりに理解したことをまとめてみます。
機能的な面で使い分けを考える
モーダルダイアログ
モーダルダイアログが開いていると、ユーザーはダイアログを処理しないとアプリに戻れません。つまり、ダイアログを閉じるかキャンセルするまで、アプリ内で他の操作ができないことを意味します。
ちなみに、ダイアログ(=dialo, dialogue)とは、対話、話し合いという意味を持ちます。つまり、UIにおけるダイアログとは、アプリとユーザー間の「対話」であり、ユーザーへの情報や行動の要求を指します。
非モーダル
非モーダルダイアログとはダイアログが開いているときでもユーザーがアプリを使用できます。つまり、ダイアログの背景要素がないという状態です。
明確に区別するため、
ダイアログ vs ポップオーバー
→ モーダル vs 非モーダル
と考えて議論することもあるそうです。
dialog要素はDialog.show()
とDialog.showModal()
を使い分けることで、モーダル/非モーダルの使い分けをすることができます。
popover
ポップオーバーとは、アプリ内でトリガーされたときに一時的に現れるウィンドウのようなUIです。ユーザーに追加情報や機能を提供するために使用されることが多いです。
Popover
は非モーダルな振る舞いをし、dialog
と比べて、静かにトリガーしたり解除したりする UI
を簡単に提供できます。
- ツールチップやヘルプテキスト
- トースト通知、ホバーカードなどの非モーダルダイアログ
といった機能を作成する時に使用します。
中間 まとめ
dialog
はモーダル/非モーダル を CSS,JS
で作成できる。
popover
はJS
を記述せずとも、非モーダルな挙動を簡単に実現できる。
以上のことから、ツールチップなどのアクション関連情報を提示するような非モーダルならpopover
を使用する方がよく、ユーザーの操作(focus
)を要求するようなモーダルを実装するなら、dialog
を使うという感じでしょうか。
属性の分類から考えてみる
結論から述べると、以下のような分類関係にあると述べています。
根拠として aria-hasPopUp に焦点を当てています。
これは、ボタンをクリック/ホバー/焦点を合わせると「ポップアップするコンテンツである」ことを理解できるように5つのroleに分類されています。
以下のように使用することで、スクリーンリーダーでは、ボタンの読み上げに加え「ポップアップがあります」「サブメニュー」といった内容が読み上げられるようになります。
<button type="button" aria-haspopup="true">メニュー</button>
dialog
がこの分類の一種であることから、
dialog
がポップオーバーの一種であることをなんとなく察することができます。
dialogの分類から考える
ダイアログは モーダル/非モーダル/アラートダイアログ の3つに分類できます。
「ポップオーバー == 非モーダル」という意見もありますが、
実際は異なるかもしれません。
なぜなら、「::backdropの存在は、その要素がモーダルであることを示唆しており、
ポップオーバーにはトップレイヤーに::backdrop疑似要素があるから」という主張があるからです
参考: https://css-tricks.com/almanac/pseudo-selectors/b/backdrop/
ポップオーバーの特徴
また、ポップオーバーにはインタラクティブな要素(ボタンなどのアクセス可能な要素)が含まれている必要があります。
ariaHasPopupにある通り、ユーザーとの対話が発生するからです。
要素によって発生させることができるメニューやダイアログなどの対話型ポップアップ要素の型と利用できるかどうかを示します。
ツールチップに対する言及
見た目上、ツールチップはポップオーバーになるはずです。
しかし、ツールチップはaria-hasPopUp
には含まれていません。
ツールチップにはインタラクティブな要素(ボタンなど操作可能な要素)が含まれることはありません。操作可能なら ダイアログを使用するべきだからです。
Semantics and the popover attribute: which role to use when?
ユーザーとの対話を望むなら、dialog
を使用した方がいいという主張の記事もあります
中間まとめ
ポップオーバーは、ユーザーの操作や特定の条件に応じて表示される様々な種類のポップアップUIを指し、これには、ツールチップ、コンテキストメニュー、モーダルダイアログ、通知など、画面上に一時的に表示される様々な要素が含まれる。
ダイアログは、ポップオーバーの一種であり、新しいカードを作成してユーザーと対話するためのインタラクティブなコンテンツを含む。
まとめ
モーダルダイアログが「ユーザーとアプリケーションの対話」するためにあるという解釈が個人的に新鮮でした。
UIコンポーネントがどのような目的で存在するのかを知っていると、自分がデザインを設計する時に、どんな時にどんなUIコンポーネントを使うべきかの取捨選択のヒントになってくれるのではないかと希望を持ちました。