2 ポイント 投稿者 GN⁺ 2024-05-11 | 1件のコメント | WhatsAppで共有
  • ブラウザの標準機能だけでページ上に表示されるポップオーバーUIを作成でき、メニュー・候補・通知のようなパターンをより一貫して実装できる
  • Popover API のポップオーバーは常に非モーダルであるため、ページ操作をブロックする必要がある UI には `` のほうが適している
  • 単純なトグルは popoverpopovertargetpopovertargetaction のようなHTML 属性で処理でき、必要に応じて JavaScript メソッドで表示状態を制御する
  • ::backdrop:popover-openbeforetoggletoggle などでスタイルや状態変化を扱え、interest invokers は JavaScript なしで hover/focus 表示をサポートする
  • 2025年1月から最新のデバイスとブラウザで動作するBaseline 2025機能だが、古い環境や一部の詳細機能の互換性は確認が必要

Popover APIが解決する問題

  • Popover API は、他のページコンテンツの上にポップオーバーコンテンツを表示する標準的な仕組みを提供する
  • ポップオーバーは HTML 属性だけで制御することもでき、JavaScript API で表示・非表示の状態を直接扱うこともできる
  • Web 上で overlays、popups、popovers、dialogs などと呼ばれてきた UI パターンを、ブラウザ標準機能としてより一貫して実装できる

モーダルが必要なら `` を使う

  • ポップオーバー UI は大きくモーダル非モーダルに分かれる
    • モーダルでは、ポップオーバー表示中はページの残り部分と対話できない
    • 非モーダルでは、ポップオーバーが表示されていてもページの残り部分と引き続き対話できる
  • Popover API で作成したポップオーバーは常に非モーダルである
  • ページ操作をブロックするモーダルなポップオーバーが必要なら `` 要素が適している
  • のようにpopover を適用する方法も有効で、ポップオーバー制御と dialog のセマンティクスを併用できる

基本的な使い方

  • Popover API は、ユーザー操作が必要な UI によく使える
    • アクションメニュー
    • カスタム toast 通知
    • フォーム要素の候補
    • コンテンツ選択 UI
    • 学習用 UI
  • HTML だけで簡単なポップオーバーのトグルボタンを作成できる
Toggle the popover
Popover content

  • JavaScript では HTMLElement.togglePopover() でポップオーバーの表示/非表示状態を切り替える
  • API は、ポップオーバーの状態変化に反応するイベントと、スタイリングを支援する CSS 機能もあわせて提供する

HTML 属性

  • interestfor
    • HTML 要素や SVG 要素をinterest invokerとして定義する
    • 値は対象要素の id であり、invoker 要素で interest が表示または消失するときに対象要素が影響を受ける
  • popover
    • 要素をポップオーバー要素に変えるグローバル属性
    • 値として "auto""hint""manual" の状態を取れる
  • popovertarget
    • または 要素をポップオーバー制御ボタンにする
    • 値は制御対象のポップオーバー要素の ID
  • popovertargetaction
    • 制御ボタンがポップオーバーに対して行う動作を指定する
    • 指定可能な値は "hide""show""toggle"

CSSで扱う表示状態

  • ::backdrop
    • ポップオーバー要素のすぐ後ろに置かれる全画面の疑似要素
    • 必要に応じてポップオーバー背後のページコンテンツにぼかしなどの効果を与えられる
  • interest-delayinterest-delay-startinterest-delay-end
    • ユーザーが interest を示した、または失った時点と、ブラウザが反応する時点の間に遅延時間を追加する
  • :interest-source:interest-target
    • interest が表示されている状態で、invoker と接続された対象要素にそれぞれスタイルを適用できる
  • :popover-open
    • ポップオーバー要素が表示中のときだけマッチする疑似クラス
    • 開いている状態のポップオーバーのスタイリングに使う

JavaScript インターフェースと DOM 拡張

  • InterestEvent
    • interestloseinterest イベントのイベントオブジェクト
    • 接続された interest invoker 要素への参照を含む source 属性を持つ
  • ToggleEvent
    • ポップオーバー要素が表示状態と非表示状態の間で切り替わるときに発生するイベントを表す
    • beforetoggletoggle イベントのイベントオブジェクト
  • interestForElement
    • interest invoker が対象とする要素への参照を取得または設定する
    • HTMLButtonElementHTMLAnchorElementHTMLAreaElementSVGAElement で使用できる
  • HTMLElement.popover
    • JavaScript で要素のポップオーバー状態を取得または設定する
    • "auto""hint""manual" の値を使い、機能検出にも利用できる
    • HTML グローバル属性 popover の値を反映する
  • popoverTargetElement
    • HTMLButtonElementHTMLInputElement で、制御ボタンが制御するポップオーバー要素を取得または設定する
    • HTML popovertarget 属性に対応する JavaScript 機能
  • popoverTargetAction
    • HTMLButtonElementHTMLInputElement で実行するポップオーバー動作を取得または設定する
    • "hide""show""toggle" の値を使い、popovertargetaction 属性を反映する

メソッドとイベント

  • HTMLElement.hidePopover()
    • ポップオーバー要素を top layer から除去し、display: none を適用して非表示にする
  • HTMLElement.showPopover()
    • ポップオーバー要素を top layer に追加して表示する
  • HTMLElement.togglePopover()
    • ポップオーバー要素を表示状態と非表示状態の間で切り替える
  • beforetoggle
    • ポップオーバー要素の状態が表示と非表示の間で切り替わる直前に発生する
    • ポップオーバーを開くのを防いだり、ポップオーバー状態に応じて他の要素を更新したりするのに使える
  • toggle
    • ポップオーバー要素の状態が切り替わった直後に発生する
  • interest
    • interest invoker の対象要素で interest が表示されると発生する
  • loseinterest
    • interest invoker の対象要素で interest が消えると発生する

例と仕様リンク

1件のコメント

 
GN⁺ 2024-05-11
Hacker News の意見
  • Popover API は、CSS アンカー位置指定(CSS Anchor Positioning) まで入ってくれば、本当に大きな変化をもたらしそう
    アンカー位置指定は、ページ上の別の要素を基準に要素を配置できるようにするもの
    Popover API と組み合わせれば、カスタムツールチップやコンテキストメニューを宣言的に実装でき、PopperJS のようなライブラリも不要になる
    https://developer.chrome.com/blog/tether-elements-to-each-ot...
    https://popper.js.org/docs/v2/

    • CSS アンカー API の使い方を扱った新しい記事をちょうど公開したところで、来週 Chromium に入る予定
      https://developer.chrome.com/blog/anchor-positioning-api
    • ブラウザのサポート状況はここで確認できる
      https://caniuse.com/css-anchor-positioning
    • この数年、CSS アンカー位置指定 があったら節約できた時間はものすごかっただろう
    • これこそ欠けていた重要なピース
      先週、新しい Popover API で何か作ってデプロイしてみようとしたが、すべてのブラウザで位置指定のサポートが不足していて、ユースケースが大きく制限された
      最後のブラウザである Firefox も、すでにベータ版でアンカー位置指定を入れているようなので、そう長くはかからなさそう
    • 2024年なのに、HTML/CSS に title のようなツールチップ属性がないのは驚き
  • モーダルダイアログが必要なら <dialog> 要素もある
    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/di...

    • 展開/折りたたみコンテンツが必要な場合や、少し無理に使えば「ドロップダウン」にも <details> を使える
      不思議なことに、<dialog><details> と違って、<popover> は属性だけで宣言的に open 状態を作れないように見える
      欠けている機能のように感じるし、この判断に根拠があったことを願う
      https://developer.mozilla.org/en-US/docs/Web/HTML/Element/de...
    • アニメーションと一般的なモーダル動作を、最近期待される水準に合わせるにはかなり作業が必要だと警告しておきたい
      十分可能ではあるが、決して些細な作業ではない
    • 指摘されているようにアニメーションはより難しいが、アクセシビリティを備えており、Esc キーで閉じる、組み込みの背景、組み込みのフォーカストラップをサポートしている
      Safari のサポートまでは時間がかかったが、今ではどこでも使える
      タグを自分で組み合わせるより良いと思う
    • 記事の最初の数段落ですでに扱っている
  • ホスト OS のウィンドウシステムと連携して実装されるなら、この機能は確かに必要に見える
    現在のポップオーバーは、常にうまく動くとは限らない方法で真似しなければならないため
    たとえばブラウザネイティブの <select> はブラウザウィンドウの境界を越えて展開できるので、ウィンドウに切られる心配をしなくてよいが、Quasar のようなツールキットの凝った偽 select はそれができず、配置の選択肢が制限される
    きちんとやるなら、win32 では各ポップオーバーが独自のネイティブ HWND を持ち、Cocoa/macOS では独自の NSView の中にある必要がありそう
    今のブラウザが実際にそう実装しているのか、それとも単にブラウザウィンドウ内に重ね描きしているだけなのか気になる

    • これらのポップオーバーは単なる普通の DOM ノードで、通常の CSS でスタイル指定される
      Web サイトが指定されたビューポートの外に描画できることを許可すると、alert()confirm()[title] のようなごく限られた場合を除き、ブラウザや OS のダイアログをもっともらしく真似するのがずっと簡単になる
      たとえば、ページがパスワードマネージャ拡張機能のロック解除ウィジェットを真似できる
      これは大きなセキュリティリスクであり、限定的な利点に比べて価値がないと思う
      これは理論上の懸念ではない
      詐欺師たちは何年も前から、ブラウザクロームまで含めた偽のポップアップウィンドウなど、非常にもっともらしい偽 UI を作ってきており、ドラッグすら可能だった
      ビューポート境界の外に描画できないことは、彼らが回避できなかったほぼ唯一の制限だった
    • そのような機能が現実的にどれほど役に立つのか分からない
      小さなデバイスでは Web ブラウザがほぼ常に全画面を覆い、大きなモニターでも通常は少なくとも一つの角に接している
    • 意味論的にも検出しやすくなりそう
      アクセシビリティやクロール可能性の面でもそうだし、誰かが「ポップアップ禁止」プラグインを作りたい場合にも有用
    • Firefox は技術的には、ページコンテンツの一部を別のOS レベルのウィンドウとして「飛び出させる」機能をサポートしている
      この機能は、ブラウザのメインプロセスでレンダリングされる権限付きの [X]HTML でのみ使える XUL 要素を通じて公開されている
      一般の Web ページに枠なしの OS ウィンドウを作る権限を与えたいブラウザ開発者はいないと思う
    • Web アプリが想像しているようなネイティブウィンドウシステム統合を近いうちに得られるとは思えない
      一部の標準コントロールがそのように動作するのは、OS ネイティブで実装されているために生じる OS ごとの実装上の副作用であり、必ずそう実装しなければならないわけでもない
  • ブラウザには組み込みのポップアップブロッカーがあるのに、こういう API を作るというのは少し笑える
    違いがあるのは分かるけど、それでもそう思う
    90年代後半から2000年代初頭のポップアップ/ポップアンダー戦争を覚えているくらいの年齢ではある
    その戦いには勝ったようだが、私たちの注意をめぐる戦争はまだまだ先が長い

    • 違うもの同士を比較しているように見える
      ポップオーバーは必要なときに文脈情報を見せる浮遊要素
      言及しているものはまったく別物
    • 言いたいことは分かるが、実際には比較対象ではないと思う
      ポップアップは OS にゴミのようなウィンドウをばらまき、最悪の場合はコンピュータの使用そのものを妨げる
      ポップオーバーダイアログはタブを閉じれば終わり
      このスタイルのポップオーバーは情報を見せるのにかなり有用で、すでにずいぶん前から使われてきた
      うっとうしく使われることはあり得るが、モーダルと同じように本当に多くのユースケースがある
    • こういう反応をよく見るが、少し筋が通っていない
      今でも既存の div などでポップオーバーは実装できる
      例: https://getbootstrap.com/docs/5.3/components/popovers/
      変わるのは、魔法のような追加ライブラリなしでポップオーバーを実装できる点だ
      明示的な “popover” 要素をブロックしたところで、人々はカスタムライブラリを使い続けるだけ
    • これはポップアップではない
      人々がポップアップを嫌うのは、侵入的で別ウィンドウを持つからだ
      この API は div モーダルを置き換え、開発者の時間とコードを減らしてくれる
    • もともとのポップアップ実装はアプリケーションコンテンツと OS の境界を破るもので、ポップアップブロッカーはそれを防ごうとするもの
      この API はその境界を破らない
      その境界が破られるとシステムの使いやすさと安全性が下がるので、望ましくない方向だ
  • 「Popover API で作ったポップオーバーは常に非モーダルだ。モーダルなポップオーバーを作りたいなら <dialog> 要素が適切だ」とあるが、なぜそうなのか分からない
    これはポップオーバーの正当なユースケースだ
    特に開いたときに背景をぼかすならなおさらで、ぼかされたボタンをユーザーのクリックで誤って押せるようにできるなら、その機能をなぜ提供しているのか疑問だ
    調べてみると、両者を組み合わせることはできる
    「ポップオーバー制御とダイアログの意味論を組み合わせたいなら、<dialog> 要素をポップオーバーにできる」という感じだ
    それならここでは modal のような属性のほうが筋が通るのではないかと思う
    ユースケースを明確に認めているのだから

    • おそらく理由はいくつかあるだろうが、その一つは <dialog> のほうがずっと先に存在していたからだと思う
  • とても良い
    正しく理解しているなら、新機能を導入するというより、モーダル div、マスク div、コンテナ div、面倒な位置指定 CSS が必要だった部分を単純化するもののようだ
    スタイリングを簡単にする擬似クラスも追加されていて、気に入った

    • 基本機能を JavaScript なしで使えるようにもしてくれる
      隠しチェックボックスを無理やり使わなくてよくなる
      スタイリングやアニメーション付きのポップオーバーまで JS なしでどこまでいけるかは分からないが、フォーカス処理がきちんと行われる JS なし対応は良い
      アクセシビリティ対応も組み込みだと言いたいところだが、今の仕様では見つけられなかった
      スクリーンリーダーのようなアクセシビリティツールに要素を知らせるところまで処理してくれるなら、大いに助けになる
      手動でやると、かなり簡単に抜け落ちるからだ
    • この API は JavaScript なしでも DOM からポップオーバー要素の表示状態を制御できるようにする
      間違いなく有用だ
  • デモ: https://mdn.github.io/dom-examples/popover-api

    • ネストしたポップオーバーのデモでは、Pizza から Ham へ斜めに移動できない
      Chrome でも Firefox でも、サブメニューが消える前の遅延時間を実装した人が誰もいないからだ
      数十年分のユーザー体験研究が消え去っており、ほぼ予想どおりだ
      https://mdn.github.io/dom-examples/popover-api/nested-popove...
    • ブラウザ対応表では対応していることになっているが、iOS Safari では動作しないようだ
  • かっこよく見えるが、このページにはなぜポップオーバーが何かを示す画像が一つもないのか分からない

  • 素晴らしい
    Popper を使って Stimulus で作ったカスタム実装はここにある
    https://github.com/tramlinehq/tramline/blob/main/app/javascr...
    そしてダイアログ用の実装はここにある
    https://github.com/tramlinehq/tramline/blob/main/app/javascr...