- 技術 💻
ポップオーバーとは|HTMLのpopover属性とツールチップ・モーダルの違い
結論
ポップオーバーとは、ボタンなどを押したときにページの上へ一時的に浮かび上がり、外側をクリックするか Esc キーで閉じる小さな表示のことです。HTML では要素に popover 属性を付け、ボタンに popovertarget を書くだけで、JavaScript なしで開閉できます。ホバーで出る短い説明が「ツールチップ」、背後を操作できなくする表示が「モーダル」で、ポップオーバーはその間にあたる「背後を操作できたまま重なる」表示です。
この記事でわかること
- ポップオーバー・ツールチップ・モーダル(dialog)の違いと、どれを使うかの判断表
- popover 属性の auto・manual・hint、light dismiss、JavaScript API を Chromium で動かした結果
- CSS アンカー配置で位置を決める方法、対応ブラウザ、Bootstrap のポップオーバーとの違い
「ポップオーバー」は、似た見た目の部品が多く、名前の使い分けで迷いやすい言葉です。まず、何を出したいかで部品を選ぶ流れを図にします。
flowchart LR
Q{何を出す?} -->|説明だけ| T[ツールチップ<br>popover=hint]
Q -->|部品を置く| P[ポップオーバー<br>popover=auto]
Q -->|通知を残す| N[通知・トースト<br>popover=manual]
Q -->|返事を待つ| M[モーダル<br>dialog.showModal]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| ポップオーバーとは | 操作で浮かび上がり、外側クリックや Esc で閉じる一時的な表示 | ポップオーバーとは(場面別の意味の表) |
| ポップオーバーとツールチップの違い | ツールチップは短い説明だけ。ポップオーバーはボタンやリンクも置ける | ポップオーバー・ツールチップ・モーダルの違い |
| ポップオーバーとモーダルの違い | モーダルは背後を操作できなくする。ポップオーバーは背後も押せる | dialog要素との違い |
| popover 属性の書き方 | 出す要素に popover、ボタンに popovertarget="id" | HTMLのpopover属性の使い方 |
| popover の auto・manual・hint | auto は1つずつ・自動で閉じる、manual は手で閉じる、hint はツールチップ向け | popover属性の値(auto・manual・hint)の違い |
| ボタンの横に出したい | CSS の position-area: bottom など(アンカー配置) | CSSアンカー配置でボタンの近くに出す |
| z-index が効かない・隠れる | popover は最上位レイヤーに出るので z-index も overflow も関係しない | 最上位レイヤーと z-index |
| popover の対応ブラウザ | Chrome・Edge 114、Firefox 125、Safari 17 から。Baseline 2025 | 対応ブラウザ |
| Bootstrap のポップオーバーとの違い | Bootstrap は JavaScript で初期化が要り、外側クリックでは閉じない(既定) | Bootstrapのポップオーバーとの比較 |
確認環境:Ubuntu 24.04.5 LTS の上で、Python 3.13.18 の http.server を 127.0.0.1 のポートに起動し、自作のテストページ(popover の auto・manual・hint・入れ子・popovertargetaction、z-index と overflow: hidden の親、dialog の showModal・show・popover 付き dialog・closedby、commandfor、CSS アンカー配置、interestfor、開閉アニメーション、Bootstrap 5.3.8 のポップオーバーとツールチップ)を置きました。操作は Chromium 153.0.8010.12(playwright 1.63.0・Node.js 22.23.4)からクリック・キー入力・ホバーを送り、:popover-open の状態、getBoundingClientRect の座標、elementFromPoint で一番上にある要素、getComputedStyle、beforetoggle・toggle イベントの記録、DevTools Protocol の Accessibility.getPartialAXTree・getFullAXTree(支援技術に渡される情報)を取り出しています。Bootstrap と互換性データ(@mdn/browser-compat-data 8.1.7・web-features 3.44.0)は作業場所に npm で入れました。Firefox・Safari・スマートフォンの実機は動かしておらず、対応状況は MDN の互換性データと Baseline の表示、決まりは WHATWG HTML Living Standard と MDN、Bootstrap の挙動は Bootstrap 公式ドキュメントで確かめた範囲を書いています。図は mermaid-cli 11.16.0 で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ポップオーバーとは|HTMLのpopover属性とツールチップ・モーダルの違い」
ポップオーバーとは(場面別の意味の表)
この節では、「ポップオーバー」がどの場面で何を指すのかが分かります。
IT でポップオーバー(popover)と言えば、ほとんどは「操作に応えて、他の内容の上に一時的に重なって出る表示」のことです。 Apple の Human Interface Guidelines も「コントロールや操作できる場所をクリック・タップしたときに、他の内容の上に現れる一時的なビュー」と説明しています。Web では HTML の popover 属性という決まった仕組みがあり、Bootstrap などの部品集にも同じ名前の部品があります。検索すると料理の名前も出てきますが、それは別の言葉です。
| 場面 | ポップオーバーの意味 | 例 | この記事 |
|---|---|---|---|
| Web の HTML | popover 属性を付けた要素。ブラウザーが開閉・重なり・閉じ方を受け持つ | <aside popover> | 詳しく扱う |
| JavaScript の API | Popover API。showPopover()・hidePopover()・togglePopover() と toggle イベント | el.showPopover() | 詳しく扱う |
| Bootstrap などの部品集 | ボタンの近くに題名と本文を出す部品。JavaScript で初期化する | data-bs-toggle="popover" | 比べて扱う |
| iPhone・iPad・Mac のアプリ | タップした場所から吹き出しのように出る一時的な画面(Apple の設計指針の用語) | 共有ボタンのメニュー | 一言だけ |
| デザインツール・Web 解析ツール | 画面の上に重ねて出すパネルやアンケート表示の呼び名 | アンケートの小窓 | 一言だけ |
| 料理 | 中が空洞にふくらむ焼き菓子・パン。IT とは別の言葉 | ポップオーバー(パン) | 扱わない |
この記事は、Web 制作で使う HTML の popover 属性を中心にします。意味だけを知りたい場合は、次の節の違いの表まで読めば答えが出ます。
ポップオーバー・ツールチップ・モーダルの違い
この節では、見た目が似ている3つの表示が、何で区別されるかが分かります。
3つを分けるのは見た目ではなく、「中に何を置けるか」と「開いている間、背後を操作できるか」です。 ツールチップは要素の説明文だけを出し、中にボタンは置きません。ポップオーバーはボタン・リンク・フォームを置けて、開いている間も背後のページを操作できます。モーダルは開いている間、背後を操作できなくし、閉じるまで利用者の返事を待ちます。
| 比べる点 | ツールチップ | ポップオーバー | モーダル |
|---|---|---|---|
| 出るきっかけ | ホバー・フォーカス | クリック・タップ | クリック・ページの処理 |
| 中に置くもの | 短い説明文だけ | ボタン・リンク・フォームも置ける | 確認・入力のフォームなど |
| 背後の操作 | できる | できる(押すと閉じる) | できない(inert になる) |
| 閉じ方 | ホバーやフォーカスが外れる・Esc | 外側クリック・Esc・もう一度押す | ボタン・Esc(外側クリックは既定で閉じない) |
| HTML での作り方 | popover="hint"+interestfor、title 属性 | popover(auto)+popovertarget | dialog 要素の showModal() |
| 例 | アイコンの名前、入力欄の補足 | メニュー、絞り込み、詳細の表示 | 削除の確認、ログイン、必須の同意 |
ポップオーバー(重なるだけ)
背後のボタンを押せた(Chromium で押した回数 1)
背後を押すと、同時に自動で閉じた
フォーカスは開いたボタンに残った
モーダル(背後を止める)
背後のボタンは押せなかった(押した回数 0)
外側をクリックしても閉じなかった
フォーカスは中の最初のボタンへ移った
どれを使うかの判断表
迷ったら、上から順に当てはまるかを見ます。最初に当てはまったものを選びます。
- 1返事をもらうまで先へ進ませない → モーダル(dialog の showModal)削除の確認、保存せずに閉じるかの確認、必須の同意
- 2中にボタン・リンク・入力欄がある → ポップオーバー(popover)メニュー、並べ替え・絞り込み、プロフィールの小窓
- 3自分で閉じるまで残したい・複数を同時に出す → popover="manual"保存しましたの通知、トースト、チャットの小窓
- 4短い説明を添えるだけ → ツールチップ(popover="hint")アイコンだけのボタンの名前、略語の説明
- 5ページの中で開いたままにする → details 要素や普通の表示よくある質問の開閉、説明の折りたたみ
ツールチップの中にリンクやボタンを置きたくなったら、それはポップオーバーに切り替える合図です。ホバーで出る表示は、マウスを動かすと消えてしまい、中の部品を押せないことがあるからです。
HTMLのpopover属性の使い方(最小のコード)
この節では、JavaScript を書かずにポップオーバーを開閉する最小の HTML が分かります。
出したい要素に popover 属性と id を付け、ボタンの popovertarget にその id を書きます。 popover 属性はグローバル属性なので、aside・section・nav・ul など、どの要素にも付けられます。popovertarget を書けるのは button 要素と input type="button" です。
<button popovertarget="menu">メニュー</button>
<nav id="menu" popover>
<a href="/news/">お知らせ</a>
<a href="/contact/">お問い合わせ</a>
</nav>
出す要素に popover と id を付ける
popover だけ(値なし)と popover="" は popover="auto" と同じです。付けた時点で、その要素は表示されなくなります(Chromium で display: none を確認)。
ボタンに popovertarget="id" を書く
押すたびに開く・閉じるが切り替わります。開くだけ・閉じるだけにしたいときは popovertargetaction="show"/"hide" を足します(書かないときは toggle)。
見た目と位置を CSS で整える
既定では画面の真ん中に、細い枠付きで出ます。ボタンの近くに出すなら、後の節の CSS アンカー配置を使います。
閉じ方を確かめる
外側のクリック、Esc キー、同じボタンをもう一度押す、の3つで閉じます。これらはブラウザーが受け持つので、閉じる処理のコードは要りません。
何も指定しないときの見た目(既定のスタイル)
Chromium 153 で、スタイルを何も書かずに開いたときの値を getComputedStyle で取り出しました(画面 800×600)。
| プロパティ | 実測の値 | 意味 |
|---|---|---|
| position | fixed | スクロールしても画面の同じ場所に出る |
| inset | 0px | 上下左右を 0 にして、margin で中央に寄せる |
| margin | 281px 296.016px 281px 296px | margin: auto の結果。画面の真ん中に出る |
| border・padding | 3px solid rgb(0, 0, 0)・4px | 細い黒枠と少しの余白(padding は 0.25em) |
| overflow | auto | 中身が多いとスクロールバーが出る |
| 背景・文字色 | rgb(255, 255, 255)・rgb(0, 0, 0) | Canvas・CanvasText(ダークモードでは反転) |
ボタンの横に出すつもりで top・left だけを書くと、inset: 0 と margin: auto が残って思った場所に出ません。位置を自分で決めるときは margin: 0; inset: auto; から書き始めます。
popover属性の値(auto・manual・hint)の違い
この節では、popover 属性の3つの値で、開き方・閉じ方・同時に開ける数がどう変わるかが分かります。
auto(既定)
popover か popover="auto"。外側クリックと Esc で閉じ、別の auto を開くと前のものが閉じる。
メニュー・絞り込み
manual
popover="manual"。外側クリックでも Esc でも閉じない。いくつでも同時に開ける。
通知・トースト
hint
popover="hint"。開いても auto を閉じない。別の hint は閉じる。外側クリックと Esc で閉じる。
ツールチップ
同じページに auto を3つ(メニュー・その中のサブメニュー・お知らせ)、manual を1つ、hint を2つ置き、Chromium から順に操作して「開いている popover」を記録しました。
| 操作 | 開いている popover | 分かること |
|---|---|---|
| 1. メニュー(auto)のボタンを押す | メニュー | JavaScript なしで開く |
| 2. メニューの中のサブ(auto)を押す | メニュー・サブ | 中に入れた popover は親を閉じない(入れ子) |
| 3. お知らせ(auto)を押す | お知らせ | 関係のない auto を開くと、前の auto は全部閉じる |
| 4. 外側をクリック | (なし) | light dismiss で閉じる |
| 5. メニューを開いて Esc | (なし) | Esc でも閉じる |
| 6. manual を開き、外側クリックと Esc | manual | manual は自動では閉じない |
| 7. manual のままメニューを開く | メニュー・manual | manual は auto の開閉に関わらない |
| 8. hint A を開く → hint B を開く | メニュー・manual・hint B | hint は auto を閉じず、別の hint だけを閉じる |
| 9. お知らせ(auto)を開く | お知らせ・manual | auto を開くと hint も閉じる |
入れ子として扱われるのは、HTML の中で親の popover の内側に置いた場合と、開くボタンが親の popover の中にある場合です(MDN の説明。手元ではボタンを中に置いた形で確かめました)。別の場所に置いた auto は「関係のない auto」なので、開いた瞬間に前のものが閉じます。
値の書き間違いにも決まりがあります。popover="foo" のように知らない値を書くと、HTML Living Standard の決まり(invalid value default は Manual)どおり、Chromium でも el.popover の値は "manual" になりました。自動で閉じなくなるので、閉じないときは綴りを確かめます。
light dismiss とは(外側クリック・Esc で閉じる)
light dismiss は、外側のクリックや Esc キーのような「軽い操作」で閉じる仕組みです。 auto と hint にあり、manual にはありません。手元で外側をクリックすると auto は閉じ、manual は残りました。
ここで大事なのは、外側のクリックが「閉じるためだけ」に使われるわけではないことです。メニューを開いたまま背後のボタンを押すと、メニューが閉じると同時に、背後のボタンのクリックも1回届きました。モーダルのように背後を止めたいなら popover ではなく dialog の showModal() を使います。
JavaScriptで開閉する(showPopover・togglePopover・toggleイベント)
この節では、JavaScript から popover を操作するメソッドとイベント、エラーになる場面が分かります。
開くのは showPopover()、閉じるのは hidePopover()、切り替えは togglePopover() です。 どれも popover 属性が付いた要素に対して呼びます。開閉の前に beforetoggle、後に toggle イベントが届き、e.oldState と e.newState に "open" か "closed" が入ります。
const panel = document.getElementById('panel');
panel.showPopover(); // 開く
panel.hidePopover(); // 閉じる
const opened = panel.togglePopover(); // 切り替え。開いたら true
panel.addEventListener('beforetoggle', (e) => {
if (e.newState === 'open' && !canOpen()) e.preventDefault(); // 開くのを止める
});
panel.addEventListener('toggle', (e) => {
console.log(e.oldState, '->', e.newState);
});
// 開くボタンを JavaScript から教える(Chrome 137・Firefox 144・Safari 26 から)
panel.showPopover({ source: document.getElementById('open-btn') });
Chromium 153 で各メソッドを呼んだ結果です。エラーの文言はそのまま載せます。
| 呼び方 | 結果(実測) |
|---|---|
| popover 属性のない要素で showPopover() | NotSupportedError: Failed to execute 'showPopover' on 'HTMLElement': Not supported on elements that are not popovers. |
| ページに追加していない要素で showPopover() | InvalidStateError: Failed to execute 'showPopover' on 'HTMLElement': Invalid on disconnected popover elements. |
| 開いているのにもう一度 showPopover() | エラーにならず、何も起きない |
| 閉じているのにもう一度 hidePopover() | エラーにならず、何も起きない |
| togglePopover() → togglePopover(true) ×2 → togglePopover(false) | false・true・true・false。開いていたので最初の呼び出しで閉じて false、引数 true は「開いた状態にする」、false は「閉じた状態にする」 |
| beforetoggle で preventDefault() してから showPopover() | 開かなかった(:popover-open は false) |
ボタンで1回開いて1回閉じたときのイベントの順番は、beforetoggle closed→open、toggle closed→open、beforetoggle open→closed、toggle open→closed でした。beforetoggle は開閉の直前にその場で届き、toggle は少し後にまとめて届きます。短い間に開閉をくり返すと toggle がまとめられ、記録の先頭に前の操作の分(closed→closed)が残っていました。状態を確かめるときは、イベントの回数を数えるより el.matches(':popover-open') を見るほうが確実です。
開いている間だけのスタイル(:popover-open)とアニメーション
開いている popover には CSS の :popover-open 擬似クラスが当たります。 フェードで開閉させるときは、display と overlay も transition に入れ、allow-discrete を付けます。開く瞬間の値は @starting-style で書きます。
#panel {
opacity: 0;
transition: opacity .4s,
display .4s allow-discrete,
overlay .4s allow-discrete;
}
#panel:popover-open { opacity: 1; }
@starting-style {
#panel:popover-open { opacity: 0; }
}
この CSS で開閉し、約90ミリ秒ごとに opacity と display を読み取りました。
| 経過時間 | 開くとき opacity | 閉じるとき opacity・display |
|---|---|---|
| 0ms | 0.00 | 1.00・block |
| 約93ms | 0.31 | 0.69・block |
| 約185ms | 0.71 | 0.29・block |
| 約278ms | 0.92 | 0.08・block |
| 約370ms | 0.99 | 0.01・block |
| 約464ms | 1.00 | 0.00・none |
閉じるときも、display が none になるのはアニメーションが終わってからでした。allow-discrete を外すと、閉じた瞬間に display: none になり、消えるアニメーションが見えなくなります。overlay は MDN の互換性データでは Chrome・Edge 117 から対応で、Firefox と Safari は対応していません(2026年10月29日時点)。CSS アニメーション全体の書き方は、関連記事「CSS アニメーション|transitionとkeyframesの違いと実用20選」で扱っています。
最上位レイヤー(top layer)とz-index:隠れない理由
この節では、popover がほかの要素の下に隠れたり、親で切り取られたりしない理由が実測で分かります。
開いた popover は「最上位レイヤー(top layer)」という、ページのどの要素よりも上の層に移されます。 そのため z-index の大きさ比べにも、親の overflow: hidden による切り取りにも関わりません。自作のメニューが別の要素の下に隠れる問題は、たいていこれで解決します。
テストページでは、overflow: hidden・transform・z-index: 1 の親(高さ60px)の中に、z-index: 99999 の absolute の要素と popover を置きました。さらにページ全体を z-index: 2147483647(指定できる最大の値)の要素で覆いました。
閉じている間、同じ座標で一番上にあったのは z-index 最大の覆いでした。popover を開くと、同じ座標の一番上は popover に変わりました。z-index は popover に1つも書いていません。
メニューが隠れるので z-index を大きくし続ける
手元では z-index 2147483647 の要素より上に出た
top・left だけで位置を書く
MDN もアンカー配置では margin: 0 を勧めている
背後を止めたいのに popover を使う
手元では背後のボタンが押せた回数 1 と 0
スタッキングコンテキストの仕組みと、z-index が効かない原因は、関連記事「CSS z-indexが効かない|スタッキングコンテキスト原因一覧」で扱っています。React で body の直下へ描画して重なりを避ける方法は、関連記事「React createPortalの使い方|モーダルとz-index」で扱っています。popover は、その「body の直下へ移す」工夫をブラウザーが代わりにする仕組みだと考えると分かりやすくなります。
dialog要素との違い(モーダル・非モーダル・popover付きdialog)
この節では、popover と dialog 要素の違いを、同じページで動かした結果で比べられます。
dialog の showModal() は背後を止めるモーダル、popover は背後を止めない重なりです。 dialog の show() は非モーダルですが、最上位レイヤーには入らず、普通の要素として表示されます。dialog に popover 属性を付けると、dialog の意味(支援技術に「dialog」と伝わる)を持ったまま、popover の開閉と light dismiss を使えます。
| 比べる点(実測) | dialog.showModal() | dialog.show() | popover | dialog+popover |
|---|---|---|---|---|
| 背後のボタンを押せたか | 押せない(0回) | 押せた(1回) | 押せた(1回)、同時に閉じた | 押せる、外側クリックで閉じた |
| 開いたときのフォーカス | 中の OK ボタンへ移った | 中の OK ボタンへ移った | 開いたボタンに残った | 中の OK ボタンへ移った |
| Esc で閉じるか | 閉じた | 閉じなかった | 閉じた | 閉じる(auto の popover と同じ決まり) |
| 外側クリックで閉じるか | 閉じない(closedby="any" なら閉じた) | 閉じない | 閉じた | 閉じた |
| 最上位レイヤー・背景 | 入る・::backdrop は rgba(0, 0, 0, 0.1) | 入らない(position: absolute) | 入る | 入る(open 属性は付かない) |
showModal() で開いている間に、アクセシビリティツリー(支援技術に渡される情報)を全部取り出すと、出てきた名前は dialog の中の「モーダル」「OK」だけで、背後のボタンや入力欄は消えていました。閉じると背後の部品がすべて戻りました。これが「inert(操作できず、読み上げの対象からも外れる)」の状態です。popover ではこうならず、背後の部品はツリーに残ったままです。
dialog の外側クリックで閉じる closedby 属性は、Chromium 153 で closedby="any" を付けると外側クリックで閉じ、付けないモーダルは閉じませんでした(付けないときの closedBy の値は "closerequest")。closedby は MDN の互換性データでは Chrome・Edge 134、Firefox 141 から対応し、Safari は Technology Preview だけです(2026年10月29日時点)。
JavaScript なしで dialog も開く(commandfor・command)
button の commandfor と command を使うと、popovertarget と同じように、dialog も JavaScript なしで開閉できます。 command に書ける値は show-modal・close・request-close・show-popover・hide-popover・toggle-popover と、-- で始まる独自の値です(MDN の button 要素のページ)。
<button commandfor="confirm" command="show-modal">削除</button>
<dialog id="confirm">
<p>本当に削除しますか?</p>
<button commandfor="confirm" command="close">やめる</button>
</dialog>
<button commandfor="menu" command="toggle-popover">メニュー</button>
<nav id="menu" popover>…</nav>
手元では command="show-modal" のボタンで dialog がモーダルで開き(:modal が true)、command="toggle-popover" で popover が開きました。互換性データでは Chrome・Edge 135、Firefox 144、Safari 26.2 から対応で、web-features では 2025年12月12日に Baseline(Newly available)になっています。dialog を使ったモーダルの完成形のコードは、関連記事「HTML dialog要素でモーダル実装|コピペ完成版とa11y対応」で扱っています。この記事はポップオーバーの入口として、どちらを選ぶかまでを受け持ちます。
CSSアンカー配置でボタンの近くに出す(position-area)
この節では、popover を開いたボタンの下や横に出す CSS と、画面の端で向きが変わる様子が分かります。
popovertarget で結ばれたボタンと popover の間には、自動で「アンカー(基準)」の関係ができます。 そのため、popover 側に position-area を書くだけで、ボタンを基準に位置が決まります。anchor-name は書かずに済みます。
.tip {
margin: 0;
inset: auto;
position-area: bottom; /* ボタンの下・中央 */
position-try-fallbacks: flip-block; /* 下に入らなければ上へ */
}
/* 名前で結ぶ書き方(ボタンと離れた要素を基準にするとき) */
#help-btn { anchor-name: --help; }
#help { position-anchor: --help; position-area: right; }
画面 800×600 で、ボタンと popover(幅170px・高さ70px)の座標を測りました。
| 指定 | ボタンの位置 | popover の位置(実測) | 結果 |
|---|---|---|---|
| position-area: bottom | x=100 y=100 幅70 高さ24 | x=50 y=124 | ボタンの真下。左右の中央がそろう |
| bottom+flip-block(画面の下端) | x=100 y=560 | x=56 y=490 | 下に入らないので上へ反転 |
| anchor-name+position-area: right | x=300 y=100 幅70 | x=370 y=77 | ボタンの右。上下の中央がそろう |
| margin: 0 だけ(位置の指定なし) | x=100 y=300 | x=0 y=0 | inset: 0 のため画面の左上に出る |
MDN の説明では、position-area で位置を決めると自動のアンカーがそのまま使われ、anchor() 関数や anchor-center を使うときは position-anchor: auto を書いて自動のアンカーを使うと明示します。CSS アンカー配置は互換性データで anchor-name が Chrome・Edge 125、Firefox 147、Safari 26 から、position-area は Chrome・Edge 129、Firefox 147、Safari 26 からです(2026年10月29日時点)。これより前の版のブラウザーでは位置の指定が無視され、既定の画面中央に出ます。中央に出ても使える見た目にしておくと、対応していないブラウザーでも困りません。
position の fixed・absolute の考え方そのものは、関連記事「CSS positionの使い方|relative・absolute・fixed」で扱っています。
ツールチップをpopoverで作る(hint・interestfor)
この節では、ホバーやフォーカスで出るツールチップを、popover="hint" と interestfor 属性で作る方法と、title 属性との違いが分かります。
button に interestfor="id" を書くと、ホバーやフォーカスで popover が開き、外れると閉じます。 出す側を popover="hint" にすれば、開いているメニュー(auto)を閉じずにツールチップだけを出せます。
<button interestfor="save-tip">保存</button>
<p id="save-tip" popover="hint">保存(Ctrl+S)</p>
Chromium 153 で、ボタンにホバー・フォーカスしたときの動きと、アクセシビリティツリーの値を確かめました。
| 作り方 | 開くきっかけ(実測) | ボタンの説明(description) |
|---|---|---|
| title 属性 | マウスを乗せるとブラウザーが表示(見た目は変えられない) | 「保存します」が常に入った |
| aria-describedby+role="tooltip" | 表示は自分で JavaScript を書く | 「保存します(role=tooltip)」が常に入った |
| interestfor+popover="hint" | ホバーから約535ms で開いた。フォーカスでも開き、外すと閉じ、Esc でも閉じた | 閉じている間は空、開いている間は「保存します(ヒント)」 |
ホバーしてすぐ開かないのは、うっかり通過したマウスで開かないよう、少し待つ決まりになっているためです(手元の計測では約0.5秒)。interestfor は MDN の互換性データでは Chrome・Edge 142 から対応で、Firefox と Safari は対応していません(2026年10月29日時点)。対応していないブラウザーでは何も開かないので、アイコンだけのボタンには aria-label で名前を付け、説明が無くても操作できるようにしておきます。
popover="hint" も、互換性データでは Chrome・Edge 151、Firefox 153 から対応し、Safari は Technology Preview だけです。Chrome 133〜150 と Firefox 149〜152 にも hint はありますが、以前の仕様のままで動きがそろわない「一部の対応」とされています。MDN によると、hint に対応していないブラウザーでは popover="manual" として扱われ、自動では閉じません。title 属性は見た目を変えられず、いつどう出るかもブラウザー任せなので、大事な情報は title だけに入れず本文やボタンの名前にも書きます。
アクセシビリティ(aria-expanded・フォーカス順・Escで戻る)
この節では、popover が支援技術やキーボードの利用者にどう伝わるかが、実測で分かります。
popovertarget で結ぶと、ブラウザーがボタンに aria-expanded と aria-details の関係を自動で付けます。 自作のメニューで JavaScript から書き換えていた aria-expanded を、書かずに済みます。
| 確かめたこと | Chromium 153 の実測 |
|---|---|
| 閉じているときのボタン | role=button、expanded=false |
| 開いているときのボタン | role=button、expanded=true、details(popover への関係)あり |
| 開いた popover(div のまま) | role=group として渡った |
| 開いた直後のフォーカス | 開いたボタンに残る(popover の中へは移らない) |
| 開いた後に Tab を1回 | popover の中の最初のボタンへ移った(HTML では離れた場所にあっても) |
| 中のリンクにフォーカスして Esc | popover が閉じ、フォーカスは開いたボタンへ戻った |
popover の中身は HTML のどこに書いてもかまわない作りですが、キーボードでは「開いたボタンの次」に入るよう、ブラウザーが順番を入れ替えます。MDN によると、showPopover({ source }) で JavaScript から開いたときは、このフォーカス順の調整はされますが、aria-expanded などの関係は付きません。ボタンで開く popover は、なるべく popovertarget か commandfor で結びます。
出す前に確かめたい点をまとめます。
- 1開くのは button 要素かa や span に onclick ではなく button。popovertarget は button と input type="button" だけ
- 2ボタンに見える名前があるかアイコンだけなら aria-label
- 3中の部品にふさわしい要素かリンクの並びなら nav や ul、対話なら dialog に popover
- 4キーボードだけで開閉できるかTab で入れて、Esc で閉じて、ボタンへ戻るか
- 5位置の指定が効かなくても使えるかアンカー配置が無いブラウザーでは画面中央に出る
- 6背後を止める必要がないか止めるなら dialog の showModal()
popoverの対応ブラウザ(MDN・Baseline、2026年10月29日時点)
この節では、popover と関係する機能が、どのブラウザーのどの版から使えるかが分かります。
popover 属性そのものは Chrome・Edge 114、Firefox 125、Safari 17 から使えます。 MDN の Popover API のページは「Baseline 2025 Newly available(2025年1月から最新の端末とブラウザーで動く)」と表示しています。web-features 3.44.0 では Baseline になった日が 2025年1月27日で、全部そろった版は Chrome・Edge 116、iPhone の Safari 18.3 とされています。Baseline の決まりでは Newly available から30か月で Widely available になるため、まだ「以前の版のブラウザーでは動かない場合がある」段階です。
| 機能 | Chrome・Edge | Firefox | Safari |
|---|---|---|---|
| popover(auto・manual)・popovertarget・showPopover・:popover-open | 114 | 125 | 17 |
| popover="hint" | 151 | 153 | Technology Preview のみ |
| showPopover({ source }) | 137 | 144 | 26 |
| anchor-name・position-area | 125・129 | 147 | 26 |
| commandfor・command | 135 | 144 | 26.2 |
| interestfor | 142 | 対応なし | 対応なし |
| @starting-style・overlay | 117・117 | 129・対応なし | 17.5・対応なし |
表は @mdn/browser-compat-data 8.1.7 の値です。数字は「その版から対応」を表し、ブラウザーの更新とともに変わるため、使う前に MDN の各ページの互換性表を開き直します。JavaScript で対応を調べるときは、次のように書けます(Chromium 153 ではすべて true でした)。
const hasPopover = 'popover' in HTMLElement.prototype;
const hasAnchor = CSS.supports('position-area: bottom');
const hasInterest = 'interestForElement' in HTMLButtonElement.prototype;
const hasCommand = 'command' in HTMLButtonElement.prototype;
popover に対応していないブラウザーでは、popover 属性は無視され、要素は最初から表示されたままになります。以前の版の端末も対象にするサイトでは、対応を調べてから JavaScript で開閉する作りに切り替えるか、公開されている polyfill(代わりに動かすスクリプト)を使うかを決めます。
Bootstrapのポップオーバーとの比較
この節では、Bootstrap 5.3 のポップオーバー部品と HTML の popover 属性の違いが、同じ操作の結果で分かります。
Bootstrap のポップオーバーは、JavaScript で初期化して、ボタンの近くに題名と本文を出す部品です。 位置決めには Popper というライブラリーを使い、bootstrap.bundle.min.js に同梱されています。Bootstrap 公式は「パフォーマンスのため opt-in(自分で初期化する)」と書いています。
<button type="button" class="btn btn-secondary"
data-bs-toggle="popover" data-bs-title="題名" data-bs-content="本文">
Bootstrap
</button>
<script src="bootstrap.bundle.min.js"></script>
<script>
document.querySelectorAll('[data-bs-toggle="popover"]')
.forEach((el) => new bootstrap.Popover(el));
</script>
Bootstrap 5.3.8 と popover 属性で、同じ操作をした結果です。
| 比べる点(実測) | Bootstrap 5.3.8(trigger 既定の click) | HTML の popover 属性 |
|---|---|---|
| 必要な JavaScript | bootstrap.bundle.min.js 80,496バイト(gzip 23,707)と初期化のコード | 0バイト |
| JavaScript を読み込めなかったとき | 押しても何も出なかった | (JavaScript に頼らない) |
| 外側クリック | 閉じなかった | 閉じた |
| Esc キー | 閉じなかった | 閉じた |
| 出る要素 | 開くたびに body の最後へ追加され、閉じると取り除かれた | HTML に書いた要素がそのまま最上位レイヤーへ |
| ボタンへの関係 | aria-describedby(role=tooltip の要素を指す) | aria-expanded と aria-details |
| 位置・向き | placement と Popper で自動。以前の版のブラウザーでも同じ | CSS アンカー配置。対応していない版では中央 |
Bootstrap で外側クリックで閉じたいときは、data-bs-trigger="focus" にします。手元ではこれで外側クリックで閉じました。ただし Bootstrap 公式は、この使い方では button ではなく a 要素に tabindex を付けて使うよう書いています。また、ホバーだけで出す設定はキーボードの利用者が開けないので避ける、中に操作できる部品を置くときはフォーカス順に注意する、とも書いています。
1Bootstrap を使い続ける場面
すでに Bootstrap で画面を作っていて、見た目をそろえたい。対応ブラウザーの幅を広く取りたい。placement や delay を細かく決めたい。
2popover 属性に替える場面
JavaScript を減らしたい。外側クリック・Esc・フォーカスの戻りをブラウザーに任せたい。z-index の重なりで困っている。
3組み合わせる場面
Bootstrap の CSS だけを使い、開閉は popover 属性にする。見た目は .popover などの class を借り、JavaScript は読み込まない。
よくあるエラー・つまずき(症状→原因→直し方)
この節では、popover が思いどおりに動かないときの原因と直し方が分かります。
| 症状 | 原因 | 直し方 |
|---|---|---|
| ボタンを押しても開かない | popovertarget の値と id が違う。ボタンが a や span | id の綴りをそろえる。button 要素にする |
| NotSupportedError: … Not supported on elements that are not popovers. | popover 属性のない要素で showPopover() を呼んだ | 要素に popover を付ける。属性を消す処理と競合していないか見る |
| InvalidStateError: … Invalid on disconnected popover elements. | ページに追加する前に showPopover() を呼んだ | appendChild などで追加してから開く |
| 外側クリックや Esc で閉じない | popover="manual"、または値の綴り違い(知らない値は manual) | 値を auto にする。閉じるボタンを付ける |
| 別のメニューを開くと前のものが閉じる | どちらも auto で、入れ子の関係がない | 中に入れて入れ子にするか、片方を manual にする |
| ボタンの横ではなく画面の中央に出る | 既定の inset: 0 と margin: auto。アンカー配置に対応していない版 | margin: 0; inset: auto; と position-area を書く |
| ページを開いた時点で中身が見えている | popover に対応していないブラウザー。CSS で display を指定している | 対応を調べる。display は :popover-open の中で書く |
| 閉じるアニメーションが見えない | display と overlay が transition に無い・allow-discrete が無い | display・overlay を allow-discrete 付きで transition に入れる |
| 背後のボタンまで押されてしまう | popover は背後を止めない(クリックは背後にも届く) | 止めたいなら dialog の showModal() |
開閉の状態が分からなくなったときは、DevTools のコンソールで document.querySelectorAll(':popover-open') を実行すると、いま開いている popover が一覧で出ます。
よくある質問
この節では、ポップオーバーについてよく聞かれる疑問への答えが分かります。
Q. ポップオーバーとポップアップは同じですか。
ポップアップは、新しいウィンドウや画面に割り込む表示を広く指す言葉です。ポップオーバーは、ページの中で操作に応えて重なって出る表示を指し、ブラウザーの新しいウィンドウは開きません。広告などで使われる別ウィンドウのポップアップとは別のものです。
Q. ポップオーバーとドロップダウンの違いは何ですか。
ドロップダウンは、ボタンの下に選択肢の一覧が垂れ下がる形の呼び名です。HTML では、ボタンの下に出すメニューを popover と CSS アンカー配置で作れます。ドロップダウンは形の名前、ポップオーバーは重なり方の名前と考えると分けやすくなります。
Q. popover 属性は div 以外にも付けられますか。
付けられます。popover はグローバル属性なので、nav・ul・aside・section・dialog など、どの要素にも付けられます。中身に合った要素を選ぶと、支援技術に意味が伝わります。
Q. popover を開くボタンを a 要素にできますか。
popovertarget は button 要素と input type="button" だけで働きます。a 要素で開きたい場合は、JavaScript で showPopover() を呼びますが、ページを移る役割の a を開閉に使うのは避け、button にするのが基本です。
Q. 複数の popover を同時に開けますか。
auto どうしでは、入れ子の関係があるときだけ同時に開けます。関係のない auto を開くと、前のものが閉じます。いくつも同時に出したい通知などは popover="manual" にします。
Q. 開いたまま、ページをスクロールするとどうなりますか。
既定は position: fixed なので、スクロールしても画面の同じ場所に残ります。CSS アンカー配置でボタンに結んでいる場合は、ボタンを基準に位置が計算されます。
Q. 外側をクリックしても閉じないようにしたいです。
popover="manual" にします。manual は外側クリックでも Esc でも閉じないので、閉じるボタン(popovertargetaction="hide")を中に置きます。
Q. 背景を暗くできますか。
::backdrop 擬似要素で、popover の後ろの全面に色を付けられます。ただし背景を暗くしても背後は操作できるままです。操作も止めたいなら dialog の showModal() を使います。
Q. React や Vue でも使えますか。
使えます。HTML の属性なので、コンポーネントのテンプレートに書けます。属性名の書き方(大文字・小文字)は各フレームワークのドキュメントで確かめます。開閉の状態を画面の処理に使いたいときは、toggle イベントで e.newState を受け取ります。
Q. Safari で popover="hint" が自動で閉じません。
互換性データでは、Safari は hint に対応していません(Technology Preview のみ、2026年10月29日時点)。MDN によると、対応していないブラウザーでは manual として扱われるため、自動では閉じません。閉じ方を JavaScript で補うか、auto で作ります。
まとめ
この節では、記事の要点を5つに分けて振り返ります。
- ポップオーバーとは、操作に応えてページの上に重なり、外側クリックや Esc で閉じる一時的な表示。ツールチップは説明だけ、モーダルは背後を止める表示
- HTML では popover と popovertarget の2つで開閉できる。JavaScript も aria-expanded の書き換えも要らない
- 値は3つ。auto は1つずつで自動で閉じる、manual は手で閉じる、hint はツールチップ向けで auto を閉じない。知らない値は manual になる
- 開いた popover は最上位レイヤーに出る。z-index や overflow: hidden に負けず、位置は CSS アンカー配置(position-area)で決める
- popover は Baseline 2025(Newly available)。hint・interestfor・overlay は対応が分かれるので、対応していないときの動きを先に確かめる
参考・出典
この節では、この記事で確かめた公式の資料が分かります(確認日 2026年10月29日)。
- WHATWG「HTML Living Standard — The popover attribute」 https://html.spec.whatwg.org/multipage/popover.html
- MDN Web Docs「popover」 https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover
- MDN Web Docs「Popover API」 https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
- MDN Web Docs「Using the Popover API」 https://developer.mozilla.org/en-US/docs/Web/API/Popover_API/Using
- MDN Web Docs「<button>: The Button element」(popovertarget・commandfor・command・interestfor) https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/button
- web.dev「ポップオーバーとダイアログ」(Learn CSS) https://web.dev/learn/css/popover-and-dialog?hl=ja
- Bootstrap「Popovers」(v5.3) https://getbootstrap.com/docs/5.3/components/popovers/
- Apple Developer「Human Interface Guidelines — Popovers」 https://developer.apple.com/design/human-interface-guidelines/popovers
- @mdn/browser-compat-data 8.1.7・web-features 3.44.0(npm で取得した互換性データ)
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ポップオーバーとは|HTMLのpopover属性とツールチップ・モーダルの違い」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。