🎯

Anchor Positioningが全対応。HTML・CSSだけのポップオーバーが完全体に

に公開

2026年1月13日に、Firefox 147がリリースされ、「CSS Anchor Positioning」が全ブラウザ対応しました。HTML・CSSだけでポップオーバー表現をしつつ、好きな要素を基準に、ポップオーバーを表示できるようになりました。

たとえば、タスク管理のサブメニューを右側に表示する表現や、ヘッダーのユーザーアイコン下にドロップダウンメニューを表示できます。

タスク管理のサブメニューが右側に表示されている様子
タスク管理のサブメニュー

ユーザーメニューがアイコンの下に表示されている様子
ユーザーアイコンの下にドロップダウンメニューが表示される

私はずっっっとこの表現をHTML・CSSで実現したいと思っており、Firefoxの対応を待ち望んでいました。本記事で詳しく解説します。

Popover APIとは

従来、ポップオーバーを実装するには、大量のイベントリスナー、複雑な位置計算のロジック、スクロールやリサイズへの対応が必要でした。

たとえば次のようなJavaScriptのコードが必要です。

// 従来のJavaScript実装
const button = document.querySelector('.trigger');
const popover = document.querySelector('.popover');

// 表示・非表示の制御
button.addEventListener('click', () => {
  popover.classList.toggle('open');
});

// ESCキーで閉じる
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    popover.classList.remove('open');
  }
});

// 背景クリックで閉じる
document.addEventListener('click', (e) => {
  if (!popover.contains(e.target) && !button.contains(e.target)) {
    popover.classList.remove('open');
  }
});

これを毎度実装するのは、かなり面倒でした。

Popover APIで表示・非表示が簡単に

Popover APIを使うと、JavaScriptを使わず、ポップオーバーの表示・非表示がHTML属性だけで実現できます。

ボタンをクリックするとポップオーバーが開くシンプルな例です。

<button popovertarget="my-popover">開く</button>

<div id="my-popover" popover>
  <p>ポップオーバーの内容</p>
</div>

これだけで、以下の機能が自動的に実装されます。JavaScriptは不要です。

  • クリックで開閉
  • ESCキーで閉じる
  • 背景クリックで閉じる
  • 適切なフォーカス管理

popovertarget属性で開閉ボタンを指定し、popover属性で要素をポップオーバーとして宣言します。

属性 役割
popover 要素をポップオーバーとして宣言
popovertarget クリック時に開閉するポップオーバーのIDを指定
popovertargetaction 動作を指定(toggle / show / hide

なお、popovertarget属性はHTML仕様上、<button>要素と<input type="button">でのみ使用できます。<a>要素では動作しません。

https://developer.mozilla.org/ja/docs/Web/API/Popover_API

Popover APIがあっても、結局位置計算にはJavaScriptが必要

Popover APIは便利な機能ですが、ポップオーバーの位置を指定する機能はありません。ボタンの下や右側にポップオーバーを表示したい場合、従来はJavaScriptで位置を計算する必要がありました。

次のコードは、ボタンの位置を取得して、ポップオーバーの位置を計算し、CSSで位置を指定するJavaScriptの例です。リサイズやスクロールのたびに再計算が必要なので、処理負荷も大きくなってしまいます。

function updatePosition() {
  // ボタンの位置を取得して、ポップオーバーの位置を計算
  const rect = button.getBoundingClientRect();
  popover.style.top = `${rect.bottom + 8}px`;
  popover.style.left = `${rect.left}px`;
}

全ブラウザ対応したCSS Anchor Positioningで位置指定をする

今回全ブラウザで対応したCSS Anchor Positioningを使うと、CSSだけでポップオーバーの位置を指定できます。

次のHTMLを例に解説します。

<button class="button" popovertarget="my-popover">開く</button>
<div id="my-popover" popover class="popover">
  <p>ポップオーバーの内容</p>
</div>

ステップ1: ポップオーバーの基準となる要素を指定する(anchor-name

ポップオーバーの基準となる要素を、CSSのanchor-nameで定義します。アンカー(anchor)とは船のいかりのことで、そこを基準にして位置を指定します。ちなみにHTMLの<a>要素も「アンカー」です。anchor-nameには任意の名前を指定できます。

.button {
  anchor-name: --my-anchor;
}

ステップ2: ポップオーバーをアンカー要素と紐づける(position-anchor

ポップオーバーをアンカー要素と紐づけるには、position-anchorプロパティを使用します。これで、CSSではアンカー要素を基準とする位置を指定できるようになります。

.popover {
  position-anchor: --my-anchor;
}

ステップ3: ポップオーバーの位置を指定する

位置の指定方法は2種類あります。

anchor()関数

anchor()関数を使うと、アンカー要素の特定の位置を基準にした配置ができます。

.popover {
  top: anchor(bottom);   /* アンカーの下端 */
  left: anchor(left);    /* アンカーの左端 */
}

また、calc()と組み合わせて余白を調整することもできます。

.popover {
  position-anchor: --my-anchor;
  top: calc(anchor(bottom) + 8px);
  left: anchor(center);
}
説明
top アンカーの上端
bottom アンカーの下端
left アンカーの左端
right アンカーの右端
center アンカーの中央

https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Values/anchor

position-areaプロパティ

position-areaプロパティを使うと、アンカー周囲のエリアを指定して配置できます。

.popover {
  position-area: block-end;
}
配置位置
block-start
block-end
inline-start 書字方向の開始位置(LTRなら左)
inline-end 書字方向の終了位置(LTRなら右)

2つの値を組み合わせることで、斜め方向にも配置できます。

配置位置
block-start inline-end 右上
block-end inline-start 左下

https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Values/position-area_value

なお、書字方向を使ったレイアウトについては、margin-inline: auto; による話も関連しています。

https://zenn.dev/tonkotsuboy_com/articles/margin-inline_auto

シンプルなデモで挙動を確認する

さまざまな配置を試すための、シンプルなデモをつくりました。

動作している様子は次のとおりです。

ポップオーバーが上側に表示されている様子
ポップオーバーが上側に表示されている様子

ポップオーバーが右側に表示されている様子
ポップオーバーが右側に表示されている様子

https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/position-area_value

画面端ではみ出さない配置(position-try-fallbacks)

ポップオーバーを表示するとき、画面外にはみ出してしまうことがあります。position-try-fallbacksを使うと、はみ出す場合に自動で代替位置へ切り替わります。これもFirefox 147で全ブラウザ対応しました。

.popover {
  position-anchor: --my-anchor;
  position-area: block-end; /* デフォルト: 下に表示 */

  /* はみ出したら上下を反転 */
  position-try-fallbacks: flip-block;
}
動作
flip-block 上下を反転
flip-inline 左右を反転
flip-block flip-inline 両方を反転

これで、画面端でも常に見える位置にポップオーバーが表示されます。

https://developer.mozilla.org/en-US/docs/Web/CSS/position-try-fallbacks

実例

サブメニューナビゲーション

私はAnchor Positioningが出たなら、絶対にこれをCSSだけで表現したいと思っていました。メニューのサブメニューの位置をAnchor Positioningで実装します。

タスク管理のサブメニューが右側に表示されている様子
タスク管理のサブメニュー

設定のサブメニューが右側に表示されている様子
設定のサブメニュー

<nav class="menu">
  <ul class="menu-list">
    <li class="menu-item">
      <button class="menu-link" id="task-menu-anchor" popovertarget="task-submenu">
        タスク管理
        <span class="chevron">›</span>
      </button>
      <ul class="submenu" popover id="task-submenu">
        <li><a href="#">今日のタスク</a></li>
        <li><a href="#">週次タスク</a></li>
        <li><a href="#">アーカイブ</a></li>
      </ul>
    </li>
  </ul>
</nav>

前述のとおり、popovertarget属性は<button>要素で使用します(<a>要素では動作しません)。

/* メニューリンクをアンカーとして定義 */
#task-menu-anchor {
  anchor-name: --task-menu;
}

/* サブメニューの位置指定 */
.submenu {
  position-anchor: --task-menu;
  top: anchor(top);
  left: anchor(right);
}

ヘッダーのユーザーメニュー

このパターンもよく使いますね。ヘッダーのユーザーアイコン下に、ドロップダウンメニューを配置する例です。

ユーザーメニューがアイコンの下に表示されている様子
ユーザーアイコンの下にドロップダウンメニューが表示される

<header class="header">
  <button popovertarget="user-menu" class="user-icon">
    <img src="avatar.png" alt="ユーザー" />
  </button>
  <div id="user-menu" popover class="dropdown-menu">
    <a href="#">プロフィール</a>
    <a href="#">設定</a>
    <a href="#">ログアウト</a>
  </div>
</header>
.user-icon {
  anchor-name: --user-icon;
}

.dropdown-menu {
  position-anchor: --user-icon;
  top: anchor(bottom);
  right: anchor(right);
  margin-top: 8px;
}

right: anchor(right)を指定することで、ドロップダウンの右端とアイコンの右端が揃います。ヘッダー右端のアイコンからドロップダウンを表示するとき、メニューが画面外へはみ出さないための指定です。

なお、position-area: block-end inline-endだと「アンカーの右下エリアに配置」となり、ドロップダウンの左端がアンカー付近に来るため、右側にはみ出してしまいます。右端を揃えたい場合はanchor()関数を使いましょう。

ブラウザ対応状況

CSS Anchor Positioningは、2026年1月13日に全主要ブラウザで対応しました。

ブラウザ 対応バージョン リリース日
Chrome 125以降 2024年5月
Edge 125以降 2024年5月
Safari 26.0以降 2025年9月
Firefox 147以降 🎉 2026年1月

https://caniuse.com/css-anchor-positioning

まとめ

Popover APIが登場したとき、ポップオーバーがJSなしで実装できて感動しました。しかし位置指定にはCSS Anchor Positioningが必要で、Firefoxが対応するまで実務では使いづらい状況が続いていました。

Safari 26、そしてFirefox 147で全ブラウザ対応したことで、ようやくHTML・CSSだけでポップオーバーを完結できるようになりました。サブメニューやドロップダウンメニューは頻出するUIなので、すぐに使える場面は多いはずです。

参考リンク

https://developer.mozilla.org/ja/docs/Web/API/Popover_API

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_anchor_positioning

https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Anchor_positioning/Using

https://caniuse.com/css-anchor-positioning

https://www.firefox.com/en-US/firefox/147.0/releasenotes/

GitHubで編集を提案
Ubie テックブログ

Discussion