Lism Tips

Popover(クリックで開く小窓)

Popover は、ボタンを押すとそのすぐそばに小さな窓を開く UI コンポーネントです。popover 属性での作り方と、出る向き・そろえ方の指定をまとめます。

Popover は、ボタンを押すと、そのボタンのすぐそばに小さな窓(ポップオーバー)を開くコンポーネントです。ブラウザにもともとある Popover API(popover 属性と popovertarget 属性で、窓を開け閉めするしくみ)だけで動くので、JavaScript は要りません。

どんなときに使う?#

  • 言葉の補足や、ちょっとした説明を、押したときだけ見せたいとき
  • 小さなメニューや、お知らせを出したいとき

画面全体をおおって見せたいときは Modal(モーダル)、マウスを乗せたときに短い説明を出したいときは Tooltip(ツールチップ) が向いています。

使い方#

b--popover の箱の中に、開くボタン(b--popover_trigger)と窓(b--popover_popup)を入れます。ボタンの popovertarget と、窓の id に同じ名前を書きます。窓には popover="auto" を付けます。

表示例

窓の中身です。外を押すか Esc キーで閉じます。

html
<div class="b--popover">
  <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-1">開く</button>
  <div class="b--popover_popup -max-w" id="demo-pop-1" popover="auto" data-side="bottom" data-align="center" style="--max-w:16rem">
    <p>窓の中身です。外を押すか Esc キーで閉じます。</p>
  </div>
</div>
クラス 付ける場所
b--popover 全体を包む箱
b--popover_trigger 開くボタン(button 要素)
b--popover_popup 開く窓
b--popover_close 窓の中に置く、閉じるボタン(button 要素)

popover="auto" にしておけば、開け閉めの細かい動きは自分で作らなくてかまいません。ブラウザが受け持つのは次の4つです。

  • 開け閉め:ボタンを1回押すと開き、もう1回で閉じます
  • かんたんに閉じる:窓の外をクリックしても、Esc キーでも閉じます。この動きを light dismiss といいます
  • 選択の戻し先:閉じると、キーボードの選択(フォーカス)がボタンへ戻ります
  • 読み上げ用の印:開いているかどうかを表す aria-expanded(読み上げソフト向けの属性)が、ボタンの上で自動で変わります
補足

窓の中で Tab キーを押して、選択が外へ出ても、窓は開いたままです(Popover API がそう決めています)。外へ出たら閉じたいなら、focusout イベントのときに hidePopover() を呼ぶ処理を、自分で用意します。

注意
  • ボタンは button 要素で作ります。popovertarget 属性が働くのは button や input type="button" などだけです。閉じるボタンも同じです
  • 窓が閉じているとき、中身は読み上げソフトからも見えなくなります。だから、なくてはならない情報やボタンは、窓の外にも置きます
  • 窓に role は付けていません。中にフォームなどの操作をまとめて入れるなら、自分で role="dialog" と aria-label を足します

出る向きとそろえ方#

窓の data-side で出る向きを、data-align でそろえる位置を決めます。

属性 値 初期値
data-side top(上)・bottom(下)・start(左)・end(右) bottom
data-align start・center・end center

data-side が top・bottom のときは data-align が横のそろえ方に、start・end のときは縦のそろえ方になります。

表示例

bottom / start

bottom / end

top / center

html
<div class="l--cluster -g:10">
  <div class="b--popover">
    <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-2">下・左寄せ</button>
    <div class="b--popover_popup -max-w" id="demo-pop-2" popover="auto" data-side="bottom" data-align="start" style="--max-w:12rem">
      <p>bottom / start</p>
    </div>
  </div>
  <div class="b--popover">
    <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-3">下・右寄せ</button>
    <div class="b--popover_popup -max-w" id="demo-pop-3" popover="auto" data-side="bottom" data-align="end" style="--max-w:12rem">
      <p>bottom / end</p>
    </div>
  </div>
  <div class="b--popover">
    <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-4">上</button>
    <div class="b--popover_popup -max-w" id="demo-pop-4" popover="auto" data-side="top" data-align="center" style="--max-w:12rem">
      <p>top / center</p>
    </div>
  </div>
</div>
  • start・end は、文字を書く向き(書字方向)に合わせて決まります。左から右へ書くページ(dir="ltr")では start が左、end が右です。右から左へ書くページ(dir="rtl")では逆になります
  • 窓が画面のはしに入りきらないときは、自動で反対側に出ます

専用の変数#

どれも b--popover(またはその外側の要素)に書きます。窓(b--popover_popup)に書いても効きません。

変数 決めること 初期値
--popover-offset ボタンと窓のあいだのすきま var(--s5)
--popover-duration 開け閉めでふわっと変わる時間 0.15s
--popover-arrow 吹き出しの矢印の高さ(0 で矢印なし) 6px

動きを減らす設定(prefers-reduced-motion: reduce)の画面では、開け閉めの時間は 0s になります。

見た目を変える#

窓は、はじめは背景が var(--base)、余白が 0.75em 1em、影の付いたカードの形です。角は丸くありません。色・余白・角丸・影は、-bgc・-c・-p・-bdrs・-bxsh などのクラスで変えます。矢印は窓の背景の色に合わせて変わり、-bd で枠線を付けると、矢印にも同じ色と太さの縁が付きます。

表示例

背景と文字の色を入れかえました。

矢印にも縁が付きます。

html
<div class="l--cluster -g:10">
  <div class="b--popover">
    <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-5">色を変える</button>
    <div class="b--popover_popup -bgc:text -c:base -max-w" id="demo-pop-5" popover="auto" data-side="bottom" data-align="center" style="--max-w:12rem">
      <p>背景と文字の色を入れかえました。</p>
    </div>
  </div>
  <div class="b--popover">
    <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-6">枠線を付ける</button>
    <div class="b--popover_popup -bd -bdc:current -max-w" id="demo-pop-6" popover="auto" data-side="bottom" data-align="center" style="--bdw:2px;--max-w:12rem">
      <p>矢印にも縁が付きます。</p>
    </div>
  </div>
</div>

閉じるボタンで閉じる(manual)#

窓を popover="manual" にすると、外を押しても Esc キーでも閉じなくなります。そのため、閉じるボタンを必ず置きます。閉じるボタンには popovertarget と popovertargetaction="hide" を付けます。

表示例

お知らせ

閉じるボタンを押すまで開いたままです。

html
<div class="b--popover">
  <button class="b--popover_trigger set--plain -bd -px:15 -py:5 -bdrs:10 -hov:-bgc" type="button" popovertarget="demo-pop-7">お知らせを見る</button>
  <div class="b--popover_popup -max-w -bd" id="demo-pop-7" popover="manual" data-side="bottom" data-align="center" style="--max-w:16rem">
    <div class="l--stack -g:5">
      <div class="l--flex -ai:center -jc:between -g:15">
        <span class="-fw:bold">お知らせ</span>
        <button class="b--popover_close set--plain -fz:l -hov:-c" type="button" popovertarget="demo-pop-7" popovertargetaction="hide">×<span class="u--srOnly">閉じる</span></button>
      </div>
      <p>閉じるボタンを押すまで開いたままです。</p>
    </div>
  </div>
</div>

ブラウザによる違い#

窓をボタンのそばに置くのには、CSS Anchor Positioning(ある要素を目じるしにして、別の要素の位置を決める CSS のしくみ)を使っています。Firefox ESR 140 のように、このしくみを使えないブラウザでは、窓は画面の真ん中に出ます。そのときは、向き・そろえ方・すきまの指定は効きません。開け閉め・外を押して閉じる・選択を戻す動きは Popover API の働きなので、そのまま使えます。

しくみ#

おもな CSS は次のとおりです(位置を決める部分は長いので省いています)。

css
.b--popover {
  --duration: var(--popover-duration, 0.15s);
  --offset: var(--popover-offset, var(--s5));
  --arrow-sz: var(--popover-arrow, 6px);
  display: inline-block;
}
.b--popover_popup {
  border: none;
  font-size: var(--fz--s);
  color: var(--text);
  background-color: var(--base);
  box-shadow: var(--bxsh--30);
  overflow: auto;
  padding: 0.75em 1em;
  opacity: 0;
}
.b--popover_popup:popover-open {
  opacity: 1;
}

React・Astro で書く場合#

@lism-css/ui/react/Popover(Astro は @lism-css/ui/astro/Popover)から Popover を読み込みます。部品は <Popover.Root>・<Popover.Trigger>・<Popover.Popup>・<Popover.Close> です。<Popover.Root> の中に置くと、popovertarget と id が自動でつながります。

jsx
import { Popover } from '@lism-css/ui/react/Popover';

<Popover.Root popoverId="pop-01">
  <Popover.Trigger bd px="15" py="5" bdrs="10" hov="-bgc">開く</Popover.Trigger>
  <Popover.Popup side="top" align="start" max-w="20rem">
    <p>中身</p>
  </Popover.Popup>
</Popover.Root>
Props 決めること
popoverId <Popover.Root> 用。ボタンと窓をつなぐ名前。書かなければ自動で作られる
offset <Popover.Root> 用。ボタンと窓のすきま(--popover-offset になる)
side <Popover.Popup> 用。出る向き(data-side になる。初期値 bottom)
align <Popover.Popup> 用。そろえ方(data-align になる。初期値 center)
type <Popover.Popup> 用。auto か manual(popover 属性になる。初期値 auto)
icon <Popover.Close> 用。中身を渡さないときのアイコン(初期値 x)
srText <Popover.Close> 用。読み上げ用の文字(初期値 Close)
popoverId・id <Popover.Trigger>・<Popover.Close> の popoverId と <Popover.Popup> の id。<Popover.Root> を使わず、部品を離して置くときだけ書く
注意

<Popover.Root> の中では、部品それぞれに popoverId や id を書かないでください。一部だけに書くと、つながりが切れます。名前を決めたいときは <Popover.Root> の popoverId だけを使います。

ヒント

srText の初期値は英語の Close です。日本語のサイトでは srText="閉じる" と書くのがおすすめです。

関連するページ#

公式ドキュメント

2026年10月5日時点の内容(lism-css 1.0.1・@lism-css/ui 0.40.1)をもとに、やさしい日本語でまとめています。

ページの一覧