ポップオーバー = ヒント

公開日: 2025 年 2 月 26 日

Chrome 133 では、既存のポップオーバー機能の上に新しいモード popover="hint" を導入しています。このブラウザ管理モードでは、ツールチップなどのエフェメラル フローティング要素の作成を簡素化する新しいスタッキング コンテキストが有効になります。設計の柔軟性を維持しながら、デベロッパーの労力を削減します。

概要と歴史

Chrome 114 で導入された Popover API を使用すると、メニューやツールチップなどのアクセス可能なフローティング UI を作成できます。デフォルトでは、popover="auto" は、Popover API の概要で説明されているように、追加のスクリプトなしで、ライト閉じる機能とフォーカス管理を処理します。popover="auto" ポップオーバーを開くと、popover="auto" を持つ祖先以外の他のすべてのポップオーバーが閉じられます。これにより、最も合理的な動作を行う人間工学的な API が実現します。

ポップオーバーが他のポップオーバーを閉じる

<div id="p1" popover>First Popover</div>
<button popovertarget="p1">Open popover 1</button>
<div id="p2" popover>Second Popover</div>
<button popovertarget="p2">Open popover 2</button>

この例では、popover="auto" では一度に開くポップアップを 1 つだけ許可しているため、ポップオーバー 2 を開くと ポップオーバー 1 が閉じます。

この動作はメニューやダイアログには適していますが、複数の種類のフローティング UI を共存させる必要がある場合は問題が発生する可能性があります。たとえば、popover="auto" を使用するメニューとツールチップが競合し、ツールチップを開くとメニューが閉じる場合があります。これは珍しい状況のように思えますが、モダンなアプリケーション スタイルの UI ではよく発生します。たとえば、github.com のヘッダーのメニューでは、メニューとツールチップの両方にポップオーバーを使用しているため、特定の条件下で両方を同時に表示できます。

開いたメニュー。
GitHub メニュー。

この問題を解決する方法の一つは、ツールチップ要素に popover="manual" を使用することです。これにより、スクリプトを使用してポップオーバーを完全に制御できます。ただし、これを行うには、スタッキング動作、軽い閉じ、フォーカス管理を再実装する必要があります。これは、Popover API が処理するように設計されたタスクです。そこで、この不足している機能を提供するために API を拡張する方法を検討しました。

デベロッパー調査により、次の2 つの一般的なスタッキング コンテキストが特定されました。

  • 永続 UI: メニューやダイアログなど。
  • エフェメラル UI: ホバーカードやツールチップなど。

両方に対応するため、popover="hint" には popover="auto" とは異なる 2 つ目のスタックが導入され、ツールチップが表示されてもメニューが開いたままになります。異なる UI タイプに複数のスタッキング コンテキストを導入する(これは基本的に z-index を再発明することになります)のではなく、このアプローチでは、永続 UIauto)とエフェメラル UIhint)の 2 つの大まかなカテゴリのみを定義することで、シンプルさを維持しています。これにより、柔軟性と、ポップオーバーの使用前に直面した問題が再び発生しないことのバランスが取れています。

新しい値の動作

popover="auto"popover="hint" はどちらも軽い閉じ方をサポートしています。つまり、ユーザーが外側をクリックするか、キーボードの Esc キーを押すと自動的に閉じます。この点では、どちらのスタイルも同じです。

他のポップオーバーを強制的に非表示にする場合、popover="auto" は開いたときに他のすべての auto ポップオーバーと hint ポップオーバーを閉じ、一度にアクティブなポップオーバーが 1 つだけになるようにします(ただし、ネストされたポップオーバーは例外です。後述)。一方、popover="hint" は他の hint ポップオーバーのみを強制的に非表示にします。メニューとツールチップは開いたままで共存できます。

最も異なるのは、ネスト動作です。popover="auto" はネストをサポートしているため、子ポップオーバーを別の親ポップオーバー内で開いたままにできます。popover="hint" には特別なネスト動作があり、ここで個別の「スタック」が使用されます。hint ポップオーバーが auto ポップオーバー内にある場合、auto スタックに結合してコンテキスト グループ化を維持します。つまり、他の auto または hint ポップオーバーによって強制的に非表示になるまで開いたままになります。これにより、ツールチップが他のメニューやポップオーバーを中断しない直感的な動作が実現します。

最後に、非常に異なるユースケースの場合は、常に popover="manual" があります。このクラスには、これらの動作は組み込まれておらず、必要な機能と動作を正確に定義できます。

popover="auto" popover="hint" popover="manual"
ライトの閉じる いいえ
強制的に非表示にする: 関連のない autohint 関連性のない hint Nothing
ネスト: 特別(前述) なし - ライトを消灯しない

ホバー トリガー

一般的な UX パターンでは、ツールチップとホバーカードをホバーでトリガーします。興味のある要素に一定時間カーソルを合わせると、ホバーカードが表示されます。現在、この動作は、mouseenter イベントと mouseleave イベントのリスナーを追加するなど、JavaScript で実装する必要があります。ただし、ホバーによるトリガーを宣言型にする別の API(Interest Invokers API)が現在開発中です。

この API はまだ開発中ですが、一般的な考え方としては、多くの要素タイプに interesttarget という属性を追加し、ホバーによるトリガー動作を付与します。

<a interesttarget="my-hovercard" href="...">
  Hover to show the hovercard
</a>
<span popover="hint" id="my-hovercard">
  This is the hovercard
</span> 

上記の HTML では、<a> リンクにカーソルを合わせると、my-hovercard ポップオーバーが自動的に表示されます。ポインタをその要素から離すと、ポップオーバーは非表示になります。JavaScript は不要です。

<button>An interesting button</button>
<div popover="hint">More info about the button</div>
[popover] {
  margin: 0;
  inset: auto;
  position-area: bottom right;
}
const button = document.querySelector('button');
const popover = document.querySelector('[popover]');

button.onmouseenter = () => {
  setTimeout(() => {
    popover.showPopover({source: button});
  }, 500);
}

button.onmouseleave = () => {
  setTimeout(() => {
    popover.hidePopover();
  }, 500);
}
ツールチップ付きのボタン。
ライブで試す。

この例では、popover="hint" を使用して基本的なツールチップを作成します。このツールチップは、マウスでボタンにカーソルを合わせたときにボタンに関する詳細情報を提供します。ホバーによるアクティベーションは、mouseentermouseleave のイベント ハンドラによって提供され、0.5 秒の遅延があります。この例では処理されない詳細がいくつかあります。

  1. ポップオーバー自体にホバーしても、トリガー要素からホバーを離しても、ポップオーバーは閉じません。そのため、ポップオーバーからテキストをコピーしたり貼り付けたりすることはできません。
  2. 「デバウンス」はありません。ボタンにほんの一瞬ホバーするだけでポップオーバーがトリガーされます。遅延時間が経過する前にボタンからホバーを素早く離しても、ポップオーバーはトリガーされます。この場合、ツールチップが開いたり閉じたりするのが速く「ちらつく」ように見えます。
  3. この例はまったくアクセスできません。マウスを使用していないユーザーは、ツールチップ コンテンツにアクセスできません。

これらの欠点は、追加の JavaScript で修正できます。たとえば、ポップオーバーのキーボード ベースでのアクティベーションをサポートするには、focus(または keydownkeyup) のイベント ハンドラ)を追加する必要があります。ツールチップにアクセスできるようにするために正しく処理する必要がある点については、Sarah Higley のこちらの優れたブログ投稿をご覧ください。これらの問題(およびその他の問題)はすべて、Interest Invokers API によって宣言的に自動的に処理されます。

補足説明

詳細については、機能の説明または HTML 仕様をご覧ください。