HOME / BLOG
BLOG

CSS Anchor Positioningの使い方【Popoverをボタンの横に配置】

デフォルト画像

ツールチップやドロップダウンをボタンの近くへ置くとき、position: absoluteと座標計算を組み合わせる実装がよく使われます。しかし、スクロール、画面端、親要素のoverflowまで考えると配置処理は複雑になります。

CSS Anchor Positioningを使うと、ある要素をアンカーとして名前付けし、別の要素をその上下左右へ配置できます。この記事ではPopover APIのメニューをボタンの下へ追従させます。

Anchor Positioningの基本用語

指定役割
anchor-name基準にする要素へアンカー名を付ける
position-anchor配置する要素から使用するアンカーを指定する
position-areaアンカーの上・下・左右など配置領域を指定する
position-try-fallbacks画面端に収まらないときの代替位置を指定する

完成コード

HTML

<main class="demo-card">
  <img class="nines-logo" src="https://kjnine.com/wp-content/themes/kjnines_theme/images/svg2/nines_logo.svg" alt="NINES">
  <p class="eyebrow">ANCHOR POSITIONING</p>
  <h1>ボタンに追従するPopover</h1>

  <button class="profile-button" type="button" popovertarget="accountMenu">
    KJのメニュー
  </button>

  <nav id="accountMenu" class="account-menu" popover>
    <a href="#profile">プロフィール</a>
    <a href="#posts">投稿一覧</a>
    <a href="#logout">ログアウト</a>
  </nav>
</main>

CSS

* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #edf1f7;
  color: #111;
  font-family: system-ui, sans-serif;
}

.demo-card {
  position: relative;
  width: min(100%, 600px);
  min-height: 300px;
  padding: 40px;
  border: 1px solid #d5dce8;
  background: #fff;
}

.nines-logo {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 58px;
  opacity: 0.16;
}

.eyebrow {
  color: #0057ff;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
}

.profile-button {
  anchor-name: --profile-trigger;
  min-height: 44px;
  padding: 10px 16px;
  border: 0;
  background: #0057ff;
  color: #fff;
  cursor: pointer;
  font: inherit;
  font-weight: 800;
}

.account-menu {
  position: fixed;
  position-anchor: --profile-trigger;
  position-area: block-end span-inline-end;
  width: 220px;
  margin: 8px 0 0;
  padding: 8px;
  border: 1px solid #cfd7e5;
  background: #fff;
  box-shadow: 0 18px 48px rgb(15 30 60 / 24%);
  position-try-fallbacks: flip-block, flip-inline;
}

.account-menu a {
  display: block;
  padding: 12px;
  color: #111;
  text-decoration: none;
}

.account-menu a:hover,
.account-menu a:focus-visible {
  background: #edf3ff;
  outline: 2px solid #0057ff;
  outline-offset: -2px;
}

@supports not (position-area: block-end) {
  .account-menu {
    inset: auto 24px 24px auto;
    margin: 0;
  }
}

JavaScript

// 開閉はPopover APIへ任せるため、基本例ではJavaScript不要です。
// 対応確認が必要ならCSS.supports()を使えます。

const hasAnchorPositioning = CSS.supports('position-area: block-end');
console.log({ hasAnchorPositioning });

アンカーへ名前を付ける

基準にするボタンへanchor-name: --profile-trigger;を指定します。カスタムプロパティに似ていますが、ここではアンカーを識別する名前です。ページ内で用途が分かる名前にします。

配置する要素から参照する

Popover側へposition-anchor: --profile-trigger;を指定し、position-area: block-end span-inline-end;で基準要素の下側へ配置します。横書きだけを前提にしたtop・rightではなく、block・inline方向を使うと書字方向へ対応しやすくなります。

画面端で位置を切り替える

メニューが画面下に収まらない場合、固定位置のままだと内容が見切れます。position-try-fallbacksflip-blockflip-inlineを指定すると、反対側へ切り替える候補を持たせられます。

フォールバックを必ず用意する

新しいCSS機能を使うときは、未対応環境でも操作できることを優先します。サンプルでは@supports not (position-area: block-end)を使い、対応していない場合は画面右下へ固定表示します。位置が理想通りでなくても、メニューを読んで操作できれば段階的な強化になります。

absolute配置との違い

方法長所注意点
position: absolute広く使える、単純な配置に強い基準にする包含ブロックの管理が必要
JavaScript座標計算細かな制御ができるスクロール・リサイズ・画面端の処理が増える
Anchor PositioningCSSで要素間の位置関係を表現できる対応状況とフォールバックを確認する

実装時のチェック項目

  • 画面の上・下・左・右の端で開く
  • ページをスクロールした状態で開く
  • メニュー項目を長い日本語へ変える
  • 200%ズームでも操作できるか確認する
  • 未対応環境で内容が消えないか確認する

CodePen埋め込み用エリア

CSS Anchor Positioningでボタンに追従するメニュー
ここにCodePenのEmbedコードを貼り付けます。Pen作成後、このブロックと埋め込みタグを差し替えてください。

HTMLとCSSを貼るだけで基本動作を確認できます。CodePenの表示幅を狭くし、ボタンを画面端へ寄せて、フォールバック位置がどう変わるか試してください。

あわせて読みたい

参考資料

まとめ

CSS Anchor Positioningは、ボタンとメニューのような要素間の位置関係をCSSで表現する仕組みです。anchor-nameで基準を作り、position-anchorposition-areaで配置し、画面端と未対応環境のフォールバックまで用意しましょう。