かつてはJavaScriptで書かないと実現できなかったポップオーバーですが、popover属性を使うことでHTMLだけで実現することが可能になりました。
popoverの基本的な使い方からアニメーションの表現の仕方など実際に見ていきましょう。
popoverを使ってみよう
popoverの使い方は簡単です。
まずは、「https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/popover」の参考の通り作ってみましょう。
<!-- 開閉するトリガー -->
<button popovertarget="my-popover">ポップオーバーを開く</button>
<!-- 開く対象 -->
<div popover id="my-popover">私から皆さんへ、こんにちは!</div>開く対象に対して、popover属性とidを指定します。そして、ポップオーバーを開くキッカケとなる要素に対して、popovertarget属性を追加して、値として開く対象のidを指定してあげてください。
開くキッカケとなる要素として指定できるのは、buttonとinput[type="button"]だけです。
ボタンをクリックすると、ポップアップが開いたり閉じたりします。これが基本的な使い方です。
開閉の役割を限定する
popovertargetを指定しただけだと、開閉のどちらの役割もある状態となります。ポップアップが閉じていれば開いて、開いていれば閉じます。
この開閉の役割を明示的に指定することも可能です。指定できるのは
- 開くだけ
- 閉じるだけ
- 開閉
の3パターンです。
役割を与えるには、トリガーにpopovertargetactionという属性を追加します。値としては以下の通りです。
- 開くだけ:
popovertargetaction="show" - 閉じるだけ:
popovertargetaction="hide" - 開閉:
popovertargetaction="toggle"
使い所としては、大きなポップアップを開くときの開くボタン、開いたポップアップ内に閉じるボタンを配置して閉じるという表現はよくあるように思います。
ポップアップの表示をCSSで調整する
ポップアップする要素にはブラウザでデフォルトのCSSが付いています。例えば、Chromeだと以下の通り、中身のコンテンツのサイズで上下左右中央に配置されるような設定となっております。
[popover] {
position: fixed;
width: fit-content;
height: fit-content;
color: canvastext;
background-color: canvas;
inset: 0px;
margin: auto;
border-width: initial;
border-style: solid;
border-color: initial;
border-image: initial;
padding: 0.25em;
overflow: auto;
}
[popover]:not(:popover-open):not(dialog[open]) {
display: none;
}このままだと、コンテンツが多くて画面いっぱいになった時に上下左右が隙間なく画面いっぱいにくっついてしまうので、少し余裕を持たせるために最大サイズを決めてみます。
[popover] {
--popover-margin: 20px;
max-inline-size: calc(100vi - var(--popover-margin) * 2);
max-block-size: calc(100vb - var(--popover-margin) * 2);
}ポップアップの背景を装飾する
ポップアップが開かれた時の周りを装飾するための::backdropという擬似要素が用意されています。例えば透過した背景を当てる場合に、
<!-- 開閉するトリガー -->
<button popovertarget="my-popover">ポップオーバーを開く</button>
<!-- 開く対象 -->
<div popover id="my-popover">私から皆さんへ、こんにちは!</div>以下のように対象のpopover属性を指定した要素に対して、CSSの表現を適応することが可能です。※ 特定のpopoverだけにしたい場合はクラスを追加してそちらに::backdropを指定してください。
[popover]::backdrop {
background-color: rgb(0 0 0 / 50%);
}開く時にアニメーションさせる
ポップアップが開く時と閉じる時にアニメーションを追加しましょう。popover属性の要素は初期状態だとdisplay: none;されている状態となります。
ポップオーバー要素は、呼び出し/制御要素(すなわち
<button>または<input type="button">にpopovertarget属性が付いたもの)、またはHTMLElement.showPopover()の呼び出しによって開かれるまで、display: none で非表示になっています。https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/popover
display: none;から表示に切り替わる際にもアニメーションしてもらえるように、@start-styleを使って非表示になっている要素の最初の状態を定義します。
@starting-styleは、最上位レイヤーに表示される要素(ポップオーバーやモーダルダイアログ (<dialog>) など)、display: noneに変更される要素、 DOM に追加されたり除去されたりする要素の出現・消滅トランジションを作成する場合に特に有益です。https://developer.mozilla.org/ja/docs/Web/CSS/@starting-style
では、CSSを書いていきましょう。今回はscaleが0から1になる、ということで作ってみます。
まずは、開いた時の状態を作成しましょう。popover属性が付与された要素に対して、開いた後のCSSを定義できる:popover-openという擬似クラスが用意されています。ここに開いた後のscaleを1として定義します。transitionもscaleに対して定義しておきましょう。
[popover] {
--animation-duration: 0.3s;
scale: 0;
transition: scale var(--animation-duration);
}
[popover]:popover-open {
scale: 1;
}続いて、@starting-styleで開く前のscaleを0として伝えておきましょう。分けて書くこともできますが、入れ子で書いておくとまとまりが分かりやすいかと思います。
[popover] {
--animation-duration: 0.3s;
scale: 0;
transition: scale var(--animation-duration);
}
[popover]:popover-open {
scale: 1;
@starting-style {
scale: 0;
}
}これで、非表示から表示される際もアニメーションが機能するようになりました。
閉じる時にアニメーションさせる
ただ、表示から非表示になる時のアニメーションが機能していません。これは、閉じるアニメーションが終わる前にdisplay: none;に切り替わっているからです。
アニメーションが終わってからdisplay: none;に切り替わってもらえるように指定を追加する必要があります。また、最上位レイヤーから除去されるの待ってもらうためにoverlayも指定しておきましょう。
それが、transition-behavior: allow-discrete;という指定です。allow-discreteを指定することによって、displayのようにnoneかblockのどちらかで表現されるようなプロパティに対しても、transitionを機能させることができるようになります。
[popover] {
--animation-duration: 0.3s;
scale: 0;
transition: scale var(--animation-duration), display var(--animation-duration) allow-discrete, overlay var(--animation-duration) allow-discrete;
}
[popover]:popover-open {
scale: 1;
@starting-style {
scale: 0;
}
}これで閉じるときもアニメーションするようになりました。
背景もアニメーションさせる
@starting-styleを使って背景も同様にアニメーションが可能です。
開く時は以下の通りです。
[popover] {
--animation-duration: 0.3s;
}
[popover]::backdrop {
background-color: rgb(0 0 0 / 0%);
transition: background-color var(--animation-duration);
}
[popover]:popover-open::backdrop {
background-color: rgb(0 0 0 / 50%);
@starting-style {
background-color: rgb(0 0 0 / 0%)
}
}そして閉じるときもアニメーションしてもらうために、displayとoverlayに対してallow-discreteを追加しましょう。
[popover] {
--animation-duration: 0.3s;
}
[popover]::backdrop {
background-color: rgb(0 0 0 / 0%);
transition: background-color var(--animation-duration), display var(--animation-duration) allow-discrete, overlay var(--animation-duration) allow-discrete;
}
[popover]:popover-open::backdrop {
background-color: rgb(0 0 0 / 50%);
@starting-style {
background-color: rgb(0 0 0 / 0%)
}
}背景もアニメーションしていることが確認できました。
