株式会社アスタスタ
WEB技術

わー!となる「CSS Anchor Positioning」

Webエンジニア S.S.

2026.8.4

とても話題になっていた「CSS Anchor Positioning」。
気が付いたら最新バージョンのブラウザであればかなり対応が進んでいたので、やっと試してみました。

「CSS Anchor Positioning」とは

CSS Anchor Positioningは、特定の要素(アンカー要素)を基準として、別の要素の位置などの設定が出来るCSSです。

「CSS Anchor Positioning(CSS アンカー位置指定)」とは(MDN):
https://developer.mozilla.org/ja/docs/Web/CSS/Guides/Anchor_positioning

anchor()関数とは(MDN):

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

position-areaプロパティとは(MDN):
https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Properties/position-area

【基本の構造】

HTML

<!-- アンカーとなる要素 -->
<button class="anchor">詳細を見る</button>

<!-- ターゲットとなる要素 -->
<div class="target">詳細の内容です</div>

CSS

/* アンカーとなる要素 */
.anchor {
  anchor-name: --is-anchor; /* アンカーに名前をつける */
}

/* ターゲットとなる要素 */
.target {
  position-anchor: --is-anchor; /* どのアンカーを基準にするか指定 */
  
  position: absolute;
  bottom: anchor(top);
  left: anchor(left);
}

たとえば上記のコードだけで、

↑このように、詳細を見るボタンの真上に、ターゲットとなる要素が表示されます。とっても便利ですね。

anchor()関数はいろいろな書き方ができます。

/* calc計算も可能です。例:アンカー要素からテキストサイズ分空けたい場合 */
bottom: calc(anchor(top) + 1em);

/* 以下のようにも書けます */
bottom: anchor(--is-anchor top);
left: anchor(--is-anchor left);

【 position-area プロパティで配置位置の調整も可能】

3×3のグリッドをイメージしつつ、ターゲットとなる要素を表示させる位置をどこにするかを調整できます。

たくさん設定方法があるのですが、よく使いそうなものを紹介しておきます。
(このあと、こちらを使ったツールチップ例をご紹介いたします)

/* 上側の中央寄せ */
position-area: top;

/* 下側の中央寄せ */
position-area: bottom;

/* 左側の中央寄せ(垂直に中央) */
position-area: left;

/* 右側の中央寄せ(垂直に中央) */
position-area: right;

さらに、position-tryでターゲットとなる要素が画面からはみ出した場合の制御ができたり等、いろいろ調整できるようですね。
(複雑だったので、今回は割愛しています)

基本が見えたところで、いろいろやってみたいと思います。

やってみる

最後にCodePenのまとめがあります。

【1. よくあるツールチップ】

よくあるツールチップ。(最近見なくなった気がする気もします)
ツールチップの位置を上下左右それぞれ指定してみます。

先ほどご紹介した position-area プロパティも出てきます。

HTML

<div>
  <button type="button" class="anchor-btn is-pos-top">ホバーすると上に表示</button>
  <div class="tooltip-box is-pos-top">補足テキストです!</div>
</div>

<div>
  <button type="button" class="anchor-btn is-pos-right">ホバーすると右に表示</button>
  <div class="tooltip-box is-pos-right">補足テキストです!</div>
</div>   
   
<div>
  <button type="button" class="anchor-btn is-pos-bottom">ホバーすると下に表示</button>
  <div class="tooltip-box is-pos-bottom">補足テキストです!</div>
</div>

<div>
  <button type="button" class="anchor-btn is-pos-left">ホバーすると左に表示</button>
  <div class="tooltip-box is-pos-left">補足テキストです!</div>
</div>

SCSS(一部抜粋)

.anchor-btn {
  padding: var(--anchor-btn-padding);
  border-radius: var(--anchor-btn-radius);
  background: var(--anchor-btn-bg);

  &.is-pos-top { anchor-name: --tooltip-anchor-top; }
  &.is-pos-bottom { anchor-name: --tooltip-anchor-bottom; }
  &.is-pos-left { anchor-name: --tooltip-anchor-left; }
  &.is-pos-right { anchor-name: --tooltip-anchor-right; }
}

/* ターゲットとなる要素 ツールチップ部分 */
.anchor-btn-tooltip {
  position: absolute;
  background: var(--tooltip-bg);
  color: var(--tooltip-color);
  padding: var(--tooltip-padding);
  border-radius: var(--tooltip-radius);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;

  &.is-pos-top {
    position-anchor: --tooltip-anchor-top;
    position-area: top; /* 上側の中央寄せ */

    &::before { @include tooltip-arrow(top); }
  }

  &.is-pos-bottom {
    position-anchor: --tooltip-anchor-bottom;
    position-area: bottom; /* 下側の中央寄せ */

    &::before { @include tooltip-arrow(bottom); }
  }

  &.is-pos-left {
    position-anchor: --tooltip-anchor-left;
    position-area: left; /* 左側の中央寄せ(垂直に中央) */

    &::before { @include tooltip-arrow(left); }
  }

  &.is-pos-right {
    position-anchor: --tooltip-anchor-right;
    position-area: right; /* 右側の中央寄せ(垂直に中央) */

    &::before { @include tooltip-arrow(right); }
  }
}

/* アンカー要素をホバー・キーボードフォーカスでツールチップを表示 */
.anchor-btn:hover + .anchor-btn-tooltip,
.anchor-btn:focus-visible + .anchor-btn-tooltip {
  opacity: 1;
}

/* キーボードフォーカス時 */
.anchor-btn:focus-visible {
  outline: var(--focus-size-outline) solid var(--focus-color-outline);
  outline-offset: var(--focus-size-outline);
}

▼ポイント

  • :hover だけでなく :focus-visible

    「ホバーすると表示」だけの設定だと、キーボード操作などでアンカーとなる要素にフォーカスしてもツールチップは表示されません。
    フォーカスした時の設定も一緒に記載して、アクセシビリティ対応もしておくと親切です。

.anchor-btn:hover + .anchor-btn-tooltip,
.anchor-btn:focus-visible + .anchor-btn-tooltip {
  opacity: 1;
}

【2. 動いている要素にも!ツールチップ】

動いている要素もアンカー要素とできます。
星マークを永遠にジャンプさせて、そこにツールチップを追従させてみます。

HTML

<div class="anchor-star">★</div>
<div class="anchor-star-tooltip">お星マークに追従する</div>

SCSS

/* アンカーとなる要素 ジャンプするお星マーク */
.anchor-star {
  anchor-name: --star-anchor;
  
  font-size: 3rem;
  color: #ffca28;

  animation: jump 0.8s ease infinite alternate;
}

/* ターゲットとなる要素 ツールチップ部分 */
.anchor-star-tooltip {
  position: absolute;
  position-anchor: --star-anchor;
  top: calc(anchor(top) - 40px);
  justify-self: anchor-center; /* アンカーの中央に配置するためのプロパティ */
  
  background: #333;
  color: #fff;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 0.85rem;
  white-space: nowrap;

  &::before {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    display: inline-block;
    width: 10px;
    height: 6px;
    background: #333;
    clip-path: polygon(0 0, 100% 0%, 50% 100%);
  }
}

/* お星マークがジャンプするアニメーション */
@keyframes jump {
  0% {
    transform: translateY(0) scale(1, 0.9);
  }
  40% {
    transform: translateY(-60px) scale(0.9, 1.1);
  }
  100% {
    transform: translateY(-80px) scale(1);
  }
}

【3. よくあるナビゲーションメニュー】

メニュー項目にホバー(:hover)した時、アンカー位置が動的に変わり、背景色として指定した擬似要素がアニメーションしながら滑らかに追従します。

HTML

<nav class="anchor-nav">
  <a href="#" class="anchor-nav-item">ダッシュボード</a>
  <a href="#" class="anchor-nav-item">情報</a>
  <a href="#" class="anchor-nav-item">設定</a>
  <a href="#" class="anchor-nav-item">ログアウト</a>
</nav>

SCSS(一部抜粋)

/* メニュー全体のコンテナ */
.anchor-nav {
  position: relative;
  display: flex;
  flex-direction: column;
  width: var(--menu-width);
  background: var(--menu-bg);
  padding: var(--menu-padding);
  border-radius: var(--menu-radius);

  &::after {
    content: "";
    position: absolute;
    position-anchor: --active-item;
    inset: anchor(inside);

    z-index: 1;
    opacity: 0;
    border-radius: var(--menu-item-radius);
    background: linear-gradient(130deg, var(--color-brand-as-des-pink) 0%, var(--color-brand-as-tech-blue) 100%);
    transition: 
      top 0.3s var(--menu-transition-timing),
      bottom 0.3s var(--menu-transition-timing),
      opacity 0.2s;
  }

  &:has(.anchor-nav-item:hover)::after,
  &:has(.anchor-nav-item:focus-visible)::after {
    opacity: 1;
  }
}

/* メニューの項目 ホバー・キーボードフォーカス要素がアンカーとなる要素 */
.anchor-nav-item {
  position: relative;
  padding: var(--menu-item-padding);
  color: var(--menu-item-color);
  text-decoration: none;
  border-radius: var(--menu-item-radius);
  z-index: 2;
  transition: color 0.3s;

  &:hover,
  &:focus-visible {
    anchor-name: --active-item;
    
    color: var(--menu-item-hover-color);
  }
  
  /* キーボードフォーカス時 */
  &:focus-visible {
    outline: var(--focus-size-outline) solid var(--focus-color-outline);
    outline-offset: var(--focus-size-outline);
  }
}

▼ポイント

  • :hover だけでなく :focus-visible

    1つ目でもご紹介しましたが、こちらもフォーカスした時の設定も一緒に記載して、アクセシビリティ対応もしておくととても親切です。

&:has(.anchor-nav-item:hover)::after,
&:has(.anchor-nav-item:focus-visible)::after {
  opacity: 1;
}

&:hover,
&:focus-visible {
  anchor-name: --active-item;
  color: var(--menu-item-hover-color);
}

【4. ONOFFボタン】

ラジオボタンのチェック状態(:checked)をトリガーにしてアンカー位置が変わり、選択された側のラベルにある擬似要素がアニメーションしながら滑らかに移動します。

HTML

<div class="switch-container">
  <label class="switch-label">
    OFF
    <input type="radio" name="switch" checked>
  </label>
  <label class="switch-label">
    ON
    <input type="radio" name="switch">
  </label>
</div>

SCSS(一部抜粋)

/* スイッチ全体のコンテナ */
.switch-container {
  position: relative;
  display: inline-flex;
  background: var(--switch-bg);
  padding: var(--switch-padding);
  border-radius: var(--switch-radius);

  &::after {
    content: "";
    position: absolute;
    position-anchor: --active-toggle;
    inset: anchor(inside);
    z-index: 1;
    background: linear-gradient(130deg, var(--color-brand-as-des-pink) 0%, var(--color-brand-as-tech-blue) 100%);
    border-radius: var(--switch-highlight-radius);
    transition: 
      left 0.25s var(--switch-transition-timing),
      right 0.25s var(--switch-transition-timing),
      background-color 0.3s;
  }
}

/* スイッチボタン チェックされた要素がアンカーとなる要素 */
.switch-label {
  padding: var(--switch-label-padding);
  font-weight: bold;
  color: var(--switch-label-color);
  cursor: pointer;
  user-select: none;
  z-index: 2;
  transition: color 0.3s;

  /* reset */
  input[type="radio"] {
    appearance: none;
    padding: 0;
    border: none;
    border-radius: 0;
    outline: none;
    background: none;
    box-shadow: none;
  }

  /* チェックされた要素 */
  &:has(input:checked) {
    anchor-name: --active-toggle;
    
    color: var(--switch-label-active-color);
  }

  /* キーボードフォーカス時 */
  &:has(input:focus-visible) {
    outline: var(--focus-size-outline) solid var(--focus-color-outline);
    outline-offset: var(--focus-size-outline);
    border-radius: var(--switch-highlight-radius);
  }
}

【CodePenで確認】

紹介した4つの例をここにまとめました。実際に確認できます。
キーボードでも試してみてください。キーボード操作でフォーカスすると、同じように動作します。
(ONOFFボタンは左右キーで)

懸念点

個人的な意見ですけれども、アクセシビリティ対応を意識していないと失念しやすそうだな...と感じました。気をつけていきたいと思います。

また、Baseline 2026に「利用可能」入りとなっておりますけれども、やはり比較的新しいCSSですので動作確認をしっかりするようにしたいと思います。
事前に対応するブラウザやバージョンを確認し、新しい技術を使っても大丈夫かどうか、まだまだ気をつけていきましょう。

@supports での分岐を併記し、未対応環境でも問題ないレイアウトを用意しておくととても親切ですね。自分も意識していきたいと思います。

@supports (anchor-name: --dummy) {
  /* Anchor Positioning対応ブラウザ向けのスタイル */
}

@supports not (anchor-name: --dummy) {
  /* 未対応ブラウザ向けのスタイル */
}

まとめ

「CSS Anchor Positioning」を試してみたお話でした。
慣れるまではドキュメントを見ながらになりそうだと思いながら…ですがそれでも掴みはかなりいいですね。話題になるはずです。

新しいCSSがどんどん増えて、今までは「あと2年くらいしたら使えるかな…」と思ったりしておりましたが、最近のスピードはすごいですね。置いていかれないように勉強していきたいと思います。
最後まで読んでいただき、ありがとうございました。

share

関連する記事

この人が書いた記事