「クリックしたら小さなメニューを出したい」「ヘルプの吹き出しを表示したい」といったトグルUIは、これまで JavaScript で表示・非表示を切り替えて作るのが一般的でした。HTML の popover 属性を使うと、こうした開閉UIをJavaScriptなしで作れます。この記事では、popover 属性と popovertarget 属性の基本から、auto と manual の違い、popovertargetaction によるボタンの制御、::backdrop や :popover-open でのスタイリングまで、動かせるデモ付きで初心者向けに解説します。
目次
popover 属性は「JavaScriptなしで開閉できる非表示要素」を作る
popover 属性を付けた要素は、初期状態では画面に表示されません。そして必要なときだけ、ページのいちばん手前にあるトップレイヤー(他のすべての要素より上の層)に表示できます。つまり「ふだんは隠れていて、操作したときだけ前面にポンと出てくる」要素になります。
ポイントは、この表示・非表示の切り替えをブラウザが受け持ってくれることです。従来のように display: none をJavaScriptで付け外しする必要がなく、popover を付けた要素と、それを開くボタンを用意するだけで、開閉するトグルUIが完成します。ヘルプの吹き出し、メニュー、簡易な通知など、軽量なポップオーバーを手早く作りたい場面で活躍します。
基本の書き方は popover と popovertarget の2つ
使い方はとてもシンプルです。まず、ポップオーバーにしたい要素に popover 属性を付け、id を割り当てます。次に、それを開くボタン側に popovertarget 属性を付け、値としてポップオーバーの id を指定します。この2つを結びつけるだけで、ボタンを押すたびに開閉(トグル)できるようになります。
<!-- popovertarget にポップオーバーの id を指定する --> <button popovertarget="help">ヘルプを表示</button> <!-- popover 属性を付けた要素は初期状態で非表示 --> <div id="help" popover> <p>このボタンから設定を変更できます。</p> </div>
popover は値を省略でき、その場合は既定値の auto として扱われます。上の例では <div id="help" popover> と書いていますが、これは popover="auto" と同じ意味です。ボタンを押すと吹き出しが開き、もう一度押すか、外側をクリックするか、Esc キーを押すと閉じます。ここまでにJavaScriptは一行も書いていません。
実際に開いて動きを確かめる
次のデモは、ボタンを押すとメニューが手前に開く例です。メニュー内の「×」ボタンで閉じられるほか、メニューの外側をクリックしたり Esc キーを押したりしても閉じます。JavaScriptのタブが空のままでも、開閉がきちんと動くことを確かめてみてください。
<div class="demo">
<button popovertarget="menu" class="open-btn">メニューを開く</button>
<div id="menu" popover="auto" class="menu">
<div class="menu__head">
<span class="menu__title">メニュー</span>
<button popovertarget="menu" popovertargetaction="hide" class="menu__close" aria-label="閉じる">×</button>
</div>
<ul class="menu__list">
<li>プロフィール</li>
<li>アカウント設定</li>
<li>ログアウト</li>
</ul>
<p class="menu__hint">背景をクリック、または Esc キーでも閉じられます。</p>
</div>
</div>
body {
font-family: sans-serif;
padding: 24px;
}
.open-btn {
padding: 10px 18px;
color: #fff;
background: #007bff;
border: none;
border-radius: 6px;
font-size: 1em;
cursor: pointer;
}
/* popover 属性が付いた要素は初期状態で非表示。
トップレイヤーに表示されるので z-index の指定は不要 */
.menu {
width: 240px;
padding: 16px;
border: 1px solid #dfe3e8;
border-radius: 10px;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
}
/* :popover-open は開いている間だけ当たる擬似クラス */
.menu:popover-open {
animation: pop 0.15s ease-out;
}
@keyframes pop {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
/* ::backdrop で背景にオーバーレイを敷ける */
.menu::backdrop {
background: rgba(0, 0, 0, 0.35);
}
.menu__head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.menu__title {
font-weight: bold;
}
.menu__close {
width: 28px;
height: 28px;
color: #555;
background: #f2f5f8;
border: none;
border-radius: 6px;
font-size: 1.1em;
cursor: pointer;
}
.menu__list {
margin: 0 0 12px;
padding-left: 18px;
line-height: 1.9;
}
.menu__hint {
margin: 0;
color: #6b7280;
font-size: 0.8em;
}
メニュー内の閉じるボタンには popovertargetaction="hide" を付けています。これは「このボタンは閉じる専用」という指定です。また .menu::backdrop で背景を少し暗くし、.menu:popover-open で開いた瞬間に軽いアニメーションを付けています。これらの擬似要素・擬似クラスについては、このあと順番に見ていきます。
auto と manual で閉じ方が変わる
popover 属性には auto と manual の2つの値があり、閉じ方の挙動が変わります。特に指定しなければ auto になります。
| 値 | 外側クリック・Esc で閉じる | 同時に開ける数 |
|---|---|---|
auto(既定) | 閉じる(light-dismiss) | 1つだけ(他は自動で閉じる) |
manual | 閉じない | 複数を同時に開ける |
auto は、ポップオーバーの外側をクリックしたり Esc キーを押したりすると自動的に閉じます。この「軽い操作で閉じる」挙動をlight-dismissと呼びます。加えて、同時に開けるのは1つだけで、別の auto ポップオーバーを開くと、先に開いていたものは自動的に閉じます。メニューや吹き出しのように「開いたら1つだけ、簡単に閉じたい」UIに向いています。
一方 manual は、外側クリックや Esc では閉じません。閉じるにはボタンなどによる明示的な操作が必要で、その代わり複数のポップオーバーを同時に開いたままにできます。画面の隅に積み重ねて表示する通知(トースト)のように、勝手に消えては困るUIに向いています。
<!-- 外側クリックや Esc では閉じない。複数を同時に開ける --> <div id="toast1" popover="manual">保存しました</div> <div id="toast2" popover="manual">新着メッセージがあります</div>
popovertargetaction でボタンの動作を決める
ボタン側に popovertargetaction 属性を付けると、そのボタンが「開く・閉じる・トグルのどれを行うか」を指定できます。省略した場合は toggle(押すたびに開閉が入れ替わる)として動きます。
| 値 | ボタンの動作 |
|---|---|
toggle(既定) | 開いていれば閉じ、閉じていれば開く |
show | 開くだけ(すでに開いていれば何もしない) |
hide | 閉じるだけ |
たとえば、開くボタンと閉じるボタンを別々に用意したいときは、開く側に show、閉じる側に hide を指定します。先ほどのデモでも、メニュー内の「×」ボタンに popovertargetaction="hide" を付けて、閉じる専用のボタンにしていました。
<!-- 開く専用のボタン --> <button popovertarget="tip" popovertargetaction="show">開く</button> <div id="tip" popover> <p>ここに説明が入ります。</p> <!-- 閉じる専用のボタン(ポップオーバーの中に置ける) --> <button popovertarget="tip" popovertargetaction="hide">閉じる</button> </div>
::backdrop と :popover-open でスタイルを整える
ポップオーバーの見た目は、専用の擬似要素・擬似クラスで細かく調整できます。よく使うのが ::backdrop と :popover-open の2つです。
::backdrop は、ポップオーバーが開いているあいだ、その背後に敷かれる領域を表す擬似要素です。ここに半透明の色を指定すると、背景を暗くして手前のポップオーバーを目立たせるオーバーレイを作れます。:popover-open は、ポップオーバーが開いている状態にだけ当たる擬似クラスです。開いた瞬間のアニメーションや、開いているときだけの装飾をここにまとめられます。
/* 開いているあいだ、背景にオーバーレイを敷く */
#menu::backdrop {
background: rgba(0, 0, 0, 0.35);
}
/* 開いている状態にだけスタイルを当てる */
#menu:popover-open {
border: 2px solid #007bff;
}
dialog 要素とはどう使い分けるか
popover と似た用途の機能に <dialog> 要素があります。どちらもトップレイヤーに表示できますが、性格が異なります。<dialog> の showModal() はモーダルダイアログを作り、開いているあいだは背後の操作をブロックして、ユーザーに応答を促します。確認ダイアログや入力フォームのように「閉じるまで先に進めない」場面に向いています。
対して popover は、原則としてモーダルにはしません。背後の操作をブロックせず、外側クリックで気軽に閉じられる、より軽量なトグルUIです。メニューや吹き出し、通知のように「サッと開いてサッと閉じる」ものは popover、「ユーザーの応答を必ず受け取りたい」ものは <dialog>、と考えると選びやすくなります。
z-index の管理とブラウザ対応
ポップオーバーを実装するうえで嬉しいのが、z-index の悩みから解放されることです。popover の要素はトップレイヤーに表示されるため、ページ内の z-index の値がどうであっても、常に他の要素より手前に出ます。従来のように「ヘッダーより前に出したいのに隠れてしまう」といった重なり順の調整が要りません。
ブラウザ対応については、Popover API はモダンブラウザで広くサポートされています。ただし利用者の環境によっては古いブラウザが残っている可能性もあるため、実際に使う前には最新の対応状況を確認しておくと安心です。対応状況は MDN の各ページに掲載されているので、公開前にチェックしておきましょう。
まとめ
popover 属性を使うと、JavaScriptなしで開閉できるトグルUIを作れます。ポップオーバーにしたい要素に popover と id を付け、開くボタンに popovertarget="id" を指定するのが基本です。既定の auto は外側クリックや Esc で閉じ(light-dismiss)、同時に1つだけ開きます。manual は明示操作でのみ閉じ、複数を同時に開けます。ボタンの動作は popovertargetaction の show / hide / toggle で制御でき、見た目は ::backdrop と :popover-open で整えられます。トップレイヤーに表示されるので z-index の管理も不要です。モーダルが必要なら <dialog>、軽量なトグルUIなら popover、と使い分けて、メニューや吹き出しづくりに活用してみてください。