CSSのAnchor Positioningでツールチップを実装する

2026.02.20 09:00
2026.03.16 13:32
CSSのAnchor Positioningでツールチップを実装する

ツールチップやポップオーバーの位置決め、今までJavaScriptで頑張ってませんでしたか?
「ボタンの上に出したい」「画面端ではみ出さないように」とか、地味にめんどくさいやつです。

CSS Anchor Positioningを使うと、これがCSSだけでできるようになります。
しかも画面端での自動位置調整まで付いてきます。

今回は基本的な使い方から実践的な例まで、まとめて紹介してみます。

サンプルページを見る(ツールチップ・ポップオーバー・バリデーションのデモ)

CSS Anchor Positioningとは

CSS Anchor Positioningは、ある要素(アンカー)を基準にして別の要素を配置できるCSSの仕組みです。

たとえば「このボタンの上にツールチップを出す」みたいなことが、CSSだけで書けます。

核となるプロパティは2つです。

  • anchor-name: 基準となる要素に名前をつける
  • position-anchor: 配置したい要素から、どのアンカーに紐づけるか指定する

これだけで要素同士が紐づきます。あとは位置を指定するだけです。

これまでのツールチップ実装の課題

従来のツールチップ実装には、だいたいこんな問題がありました。

  • JSでの位置計算が必要: getBoundingClientRect()で座標を取って、top/leftを計算するコードが必要
  • 画面端でのはみ出し: ビューポートの端にある要素だとツールチップが見切れる。はみ出し検知も自前で書く必要がある
  • スクロール追従: スクロールすると位置がずれる。scroll/resizeイベントを監視して再計算が必要
  • ライブラリへの依存: Floating UIやPopper.jsを入れればラクだけど、バンドルサイズが増える

CSS Anchor Positioningなら、これらをブラウザがネイティブに解決してくれます。

基本的な使い方

最小構成を見てみます。3ステップです。

1. アンカーに名前をつける(anchor-name)

基準にしたい要素にanchor-nameを設定します。値はCSS変数と同じく--で始めます。

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

2. 配置する要素をアンカーに紐づける(position-anchor)

ツールチップなどの配置したい要素にposition-anchorを設定します。
position: absoluteまたはposition: fixedが必要です。

.tooltip {
  position: absolute;
  position-anchor: --my-button;
}

3. 位置を指定する(position-areaまたはanchor関数)

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

方法A: position-area(シンプル)

アンカーを中心にした3×3のグリッドのどこに配置するか、キーワードで指定します。

.tooltip {
  position: absolute;
  position-anchor: --my-button;
  position-area: top; /* アンカーの上に配置 */
}

使えるキーワードの例: top, bottom, left, right, top left, bottom right, center など。

方法B: anchor()関数(細かく制御)

top, leftなどのインセットプロパティでanchor()関数を使います。

.tooltip {
  position: absolute;
  position-anchor: --my-button;
  /* アンカーの上辺から8px上にずらす */
  bottom: calc(anchor(top) + 8px);
  /* アンカーの水平中央に合わせる */
  left: anchor(center);
  translate: -50% 0;
}

anchor()の引数にはtop, bottom, left, right, centerのほか、パーセント値(anchor(50%))も使えます。

実例1: シンプルなツールチップ(ホバーで表示)

まずは一番よくあるパターン。ボタンにホバーしたらツールチップが出る例です。

<div class="tooltip-wrapper">
  <button class="anchor-btn">ホバーしてね</button>
  <div class="tooltip" role="tooltip">これがツールチップです</div>
</div>
/* アンカーの設定 */
.anchor-btn {
  anchor-name: --tooltip-anchor;
}

/* ツールチップ */
.tooltip {
  position: absolute;
  position-anchor: --tooltip-anchor;
  position-area: top;
  width: max-content;
  margin-bottom: 8px;

  background: #333;
  color: #fff;
  padding: 6px 12px;
  border-radius: 4px;
  font-size: 14px;

  /* 初期状態は非表示 */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}

/* ホバー or キーボードフォーカスで表示 */
.anchor-btn:hover + .tooltip,
.anchor-btn:focus-visible + .tooltip {
  opacity: 1;
}

position-area: topでアンカーの上に配置し、margin-bottomで少し隙間を空けています。width: max-contentを入れておくと、テキストが不自然に折り返されるのを防げます。

:focus-visibleも入れておくと、キーボード操作でも表示されるのでアクセシビリティ的にも良いですね。

実例2: ポップオーバー(popover属性との組み合わせ)

HTMLのpopover属性とAnchor Positioningを組み合わせると、JSなしでポップオーバーが作れます。

<button class="info-btn" popovertarget="info-popover">
  ℹ️ 詳細
</button>

<div id="info-popover" popover="auto" class="popover-content">
  <p>この機能はベータ版です。</p>
  <p>フィードバックは<a href="#">こちら</a>からお願いします。</p>
</div>
/* ボタンをアンカーに */
.info-btn {
  anchor-name: --info-anchor;
}

/* ポップオーバーの配置 */
.popover-content {
  /* popoverのデフォルトinsetをリセット */
  inset: auto;
  margin: 0;

  position-anchor: --info-anchor;
  position-area: bottom;
  margin-top: 8px;

  /* スタイリング */
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  max-width: 300px;
}

popover属性の要素はトップレイヤーに配置されるので、z-indexの問題を気にしなくて済みます。popovertargetでボタンとポップオーバーを紐づけるので、開閉のJSも不要です。

popover="auto"にすると、外側をクリックしたときやEscキーで自動的に閉じてくれます。

注意点として、popover要素はデフォルトでinset: 0margin: autoが設定されています。Anchor Positioningで位置を制御するために、これらをリセットしておく必要があります。

実例3: フォームのバリデーションメッセージ

入力フィールドの横にエラーメッセージを表示するパターンです。

<form class="form-example">
  <div class="form-group">
    <label for="email">メールアドレス</label>
    <input
      type="email"
      id="email"
      class="form-input"
      required
      placeholder="example@mail.com"
    />
    <span class="error-msg">有効なメールアドレスを入力してください</span>
  </div>
</form>
/* 包含ブロックの設定(absoluteの基準) */
.form-group {
  position: relative;
}

/* 入力フィールドをアンカーに */
.form-input {
  anchor-name: --email-input;
}

/* エラーメッセージの配置 */
.error-msg {
  position: absolute;
  position-anchor: --email-input;
  position-area: right;
  margin-left: 12px;

  color: #dc3545;
  font-size: 13px;
  white-space: nowrap;

  /* 初期状態は非表示 */
  display: none;
}

/* バリデーション失敗時に表示 */
.form-input:invalid:not(:placeholder-shown) + .error-msg {
  display: block;
}

/* 画面が狭いときは下に配置 */
@media (max-width: 640px) {
  .error-msg {
    position-area: bottom;
    margin-left: 0;
    margin-top: 4px;
  }
}

:invalid:not(:placeholder-shown)で、ユーザーが入力してバリデーションに引っかかったときだけメッセージを表示しています。初期状態では出ません。

メディアクエリで画面幅が狭いときはposition-areabottomに変えて、フィールドの下に表示するようにしました。position-areaの値を変えるだけで配置を切り替えられるのが便利ですね。

position-areaとposition-try-fallbacksによる自動位置調整

Anchor Positioningの真骨頂がこの自動位置調整です。
画面端でツールチップがはみ出しそうなとき、自動的に別の位置にフォールバックしてくれます。

flip-blockとflip-inline

一番手軽なのは組み込みのflipキーワードです。

.tooltip {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top;

  /* 上にスペースがなければ下に反転 */
  position-try-fallbacks: flip-block;
}

/* 横方向の反転 */
.tooltip-horizontal {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: right;

  /* 右にスペースがなければ左に反転 */
  position-try-fallbacks: flip-inline;
}

/* 上下左右すべてを候補にする */
.tooltip-full {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top right;

  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
}
  • flip-block: ブロック軸(縦方向)で反転。topならbottomへ
  • flip-inline: インライン軸(横方向)で反転。rightならleftへ
  • flip-block flip-inline: 両方向を同時に反転(スペース区切りで1つのオプションとして指定)

@position-tryでカスタムフォールバック

flipだけでは足りない場合、@position-tryで独自のフォールバック位置を定義できます。

/* カスタムフォールバックの定義 */
@position-try --below {
  position-area: bottom;
  margin-top: 8px;
  margin-bottom: 0;
}

@position-try --left-side {
  position-area: left;
  margin-right: 8px;
  margin-bottom: 0;
}

.tooltip {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top;
  margin-bottom: 8px;

  /* 上 → 下 → 左 の順で試す */
  position-try-fallbacks: --below, --left-side;
}

ブラウザはまずデフォルトの位置(top)を試して、はみ出す場合は--below、それでもダメなら--left-sideを試します。

flipキーワードとカスタムオプションを混在させることもできます。

.tooltip {
  /* flip-blockを先に試して、ダメならカスタム位置 */
  position-try-fallbacks: flip-block, --left-side;
}

ブラウザ対応状況(2026年3月時点)

2026年3月時点での対応状況です。

  • Chrome / Edge: 125以降で対応(2024年5月〜)
  • Safari: 26以降で対応(2025年9月〜)
  • Firefox: 145以降で対応(2026年1月〜)

2026年1月にFirefoxが対応したことで、主要ブラウザすべてで使えるようになりました。Interop 2026の対象機能にも含まれていて、ブラウザ間の互換性も改善が進んでいます。

ただし古いバージョンのブラウザをサポートする必要がある場合は、フォールバックを用意しておくと安心です。

@supportsでのフォールバック

@supportsで機能検出して、非対応ブラウザ向けのフォールバックを書けます。

/* フォールバック: Anchor Positioning非対応ブラウザ向け */
.tooltip-wrapper {
  position: relative;
}

.tooltip {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 8px;
}

/* Anchor Positioningが使える場合は上書き */
@supports (anchor-name: --x) {
  .tooltip-wrapper {
    position: static;
  }

  .tooltip {
    position-anchor: --tooltip-anchor;
    position-area: top;
    bottom: auto;
    left: auto;
    transform: none;
    position-try-fallbacks: flip-block;
  }
}

ポイントは、まず従来の方法(position: relativeの親 + position: absoluteの子)でベースのスタイルを書いておき、@supportsの中でAnchor Positioning版に上書きするところです。

これなら非対応ブラウザでもツールチップが壊れることはありません。位置の自動調整は効きませんが、基本的な表示は保たれます。

OddBirdが提供しているポリフィルを使う手もあります。

<script src="https://unpkg.com/@oddbird/css-anchor-positioning/dist/css-anchor-positioning-fn.js"></script>
<script>
  if (!CSS.supports('anchor-name: --x')) {
    window.applyAnchorPositioning();
  }
</script>

ただし、主要ブラウザの最新版はすべて対応済みなので、ポリフィルが必要なケースは減ってきています。

JSライブラリ(Floating UI等)との使い分け

「Floating UIを使ってるけど、Anchor Positioningに置き換えるべき?」という疑問が出ると思います。
ざっくりまとめるとこんな感じです。

  • CSS Anchor Positioningが向いているケース
    • シンプルなツールチップ、ポップオーバー
    • JSの依存を減らしたい
    • パフォーマンスを重視したい(ブラウザネイティブなので高速)
    • 静的な要素同士の紐づけ
  • Floating UIが向いているケース
    • カーソル位置に追従するツールチップ(仮想要素のアンカー)
    • 複雑なインタラクション(ドラッグ&ドロップとの連携など)
    • 古いブラウザのサポートが必須
    • React/Vueなどのフレームワークとの統合が必要

個人的には、新規プロジェクトでシンプルなツールチップやドロップダウンを作るなら、まずCSS Anchor Positioningで試してみるのが良いかなと思っています。JSのバンドルサイズが減るし、スクロール時のパフォーマンスもブラウザに任せられます。

複雑なケースや古いブラウザ対応が必要なら、Floating UIの出番ですね。両方知っておいて使い分けるのがベストだと思います。

まとめ

CSS Anchor Positioningを使うと、今までJSで書いていたツールチップやポップオーバーの位置決めがCSSだけでできるようになります。

  • anchor-nameposition-anchorで要素同士を紐づける
  • position-areaanchor()関数で位置を指定
  • position-try-fallbacksで画面端の自動位置調整
  • popover属性と組み合わせるとJS完全不要のポップオーバーが作れる
  • 2026年3月時点で主要ブラウザすべてに対応済み

ブラウザのネイティブ機能なのでパフォーマンスも良く、コード量もぐっと減ります。
ツールチップの位置計算をJSで頑張っていた頃と比べると、めちゃくちゃ楽になりました。

サンプルページで実際の動きを確認する

今回は以上です!