CSS アンカー ポジショニング API のご紹介

CSS Anchor Positioning API は、アンカーと呼ばれる他の要素に対してネイティブに要素を配置できるため、ウェブ開発に大きな変化をもたらします。この API は、メニュー、サブメニュー、ツールチップ、選択、ラベル、カード、設定ダイアログなど、多くのインターフェース機能の複雑なレイアウト要件を簡素化します。ブラウザにアンカーの位置決め機能が組み込まれているため、サードパーティ ライブラリに頼ることなく多層的なユーザー インターフェースを構築でき、クリエイティブな可能性の世界が広がります。

アンカー ポジショニングは Chrome 125 以降で利用できます。

対応ブラウザ

  • Chrome: 125。 <ph type="x-smartling-placeholder">
  • Edge: 125。 <ph type="x-smartling-placeholder">
  • Firefox: サポートされていません。 <ph type="x-smartling-placeholder">
  • Safari: サポートされていません。 <ph type="x-smartling-placeholder">

ソース

基本コンセプト: アンカーと配置された要素

この API の中核にあるのは、「アンカー」と「配置された要素」の関係です。アンカーは、anchor-name プロパティを使用して基準点として指定される要素です。位置指定要素は、position-anchor プロパティを使用するか、位置指定ロジックで anchor-name を明示的に使用して、アンカーに対して相対的に配置される要素です。

<ph type="x-smartling-placeholder">
</ph>
アンカー要素と配置された要素

アンカーの設定

アンカーの作成は簡単です。選択した要素に anchor-name プロパティを適用し、一意の識別子を割り当てます。CSS 変数と同じように、この一意の識別子の前に 2 個のダッシュを付ける必要があります。

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

アンカー名を割り当てると、.anchor-button はアンカーとして機能し、他の要素の配置を指示できるようになります。このアンカーを他の要素に接続するには、次の 2 つの方法があります。

暗黙的アンカー

アンカーを別の要素に接続する 1 つ目の方法は、下記のコードサンプルのように「暗黙的アンカー」を使用することです。アンカーに接続する要素に position-anchor プロパティを追加し、値としてアンカーの名前(この場合は --anchor-el)を指定します。

.positioned-notice {
    position-anchor: --anchor-el;
}

暗黙的なアンカー関係では、最初の引数でアンカー名を明示的に指定しなくても、anchor() 関数を使用して要素を配置できます。

.positioned-notice {
    position-anchor: --anchor-el;
    top: anchor(bottom);
}

明示的アンカー

または、アンカー関数でアンカー名を直接使用することもできます(例: top: anchor(--anchor-el bottom)。これは「明示的アンカー」と呼ばれ、複数の要素を固定したい場合に便利です(後述)。

.positioned-notice {
    top: anchor(--anchor-el bottom);
}

アンカーを基準として要素を配置する

<ph type="x-smartling-placeholder">
</ph>
物理的特性によるアンカー ポジショニングの図。

アンカー ポジショニングは、CSS の絶対位置に基づいて構築されます。ポジショニングの値を使用するには、配置する要素に position: absolute を追加する必要があります。次に、anchor() 関数を使用して位置の値を適用します。たとえば、アンカー要素をアンカー要素の左上に配置するには、次のように配置します。

.positioned-notice {
    position-anchor: --anchor-el;
    /* absolutely position the positioned element */
    position: absolute;
    /* position the right of the positioned element at the right edge of the anchor */
    right: anchor(right);
    /* position the bottom of the positioned element at the top edge of the anchor */
    bottom: anchor(top);
}
<ph type="x-smartling-placeholder">
</ph>
配置された要素上のエッジの配置を示す図。

次のように、1 つの要素を別の要素に固定しました。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
基本的なアンカーのデモ。

デモのスクリーンショット。

これらの値に論理的位置を設定する場合、同等のものは次のようになります。

  • top = inset-block-start
  • left= inset-inline-start
  • bottom = inset-block-end
  • right= inset-inline-end

anchor-center を使用して配置した要素を中央に配置する

アンカーが配置された要素をアンカーに対して中央に配置しやすくするために、anchor-center という新しい値が追加されました。この値は、justify-selfalign-selfjustify-itemsalign-items の各プロパティで使用できます。

この例では、justify-self: anchor-center を使用して、配置された要素をアンカーの上に配置することで、前の要素を変更しています。

.positioned-notice {
  position: absolute;
  /*  Anchor reference  */
  position-anchor: --anchor-el;
  /*  Position bottom of positioned elem at top of anchor  */
  bottom: anchor(top);
  /*  Center justification to the anchor */
  justify-self: anchor-center;
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。 justify-center を使用して中央に配置されたアンカーのデモ。

デモのスクリーンショット。

複数のアンカー

要素は複数のアンカーにテザリングできます。つまり、場合によっては、複数のアンカーを基準として位置する位置値を設定する必要があります。これを行うには、anchor() 関数を使用し、最初の引数でどのアンカーを参照するかを明示的に指定します。次の例では、配置された要素の左上は 1 つのアンカーの右下に固定され、配置された要素の右下は 2 つ目のアンカーの左上に固定されます。

.anchored {
  position: absolute;
  top: anchor(--one bottom);
  left: anchor(--one right);
  right: anchor(--two left);
  bottom: anchor(--two top);
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
複数のアンカーを示すデモ。

デモのスクリーンショット。

inset-area での位置

絶対位置からのデフォルトの方向配置に加えて、アンカー API には、インセット領域という新しいレイアウト メカニズムが含まれています。

インセット領域を使用すると、アンカーが配置された要素をそれぞれのアンカーに対して相対的に簡単に配置できます。9 セルのグリッドでは、アンカー要素が中央に配置されます。

インセット領域のさまざまな配置オプション(9 セル グリッド)

絶対位置ではなくインセット領域を使用するには、物理値または論理値で inset-area プロパティを使用します。例:

  • 上部中央: inset-area: top または inset-area: block-start
  • 左中央: inset-area: left または inset-area: inline-start
  • 中央下: inset-area: bottom または inset-area: block-end
  • 右中央: inset-area: right または inset-area: inline-end
で確認できます。 <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
複数のアンカーを示すデモ。

デモのスクリーンショット。

これらの位置をさらに詳しく調べるには、次のツールを確認してください。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
インセット領域の位置用のアンカーツール

anchor-size() を使用して要素のサイズを設定する

anchor-size() 関数(こちらはアンカー ポジショニング API の一部)を使用すると、アンカーのサイズ(幅、高さ、インラインとブロックのサイズ)に基づいて、アンカーが配置された要素のサイズまたは配置を行うことができます。

次の CSS は、高さにこの値を使用する例を示しています。calc() 関数内で anchor-size(height) を使用して、ツールチップの最大の高さをアンカーの高さの 2 倍に設定します。

.positioned-notice {
  position-anchor: --question-mark;

  /*  set max height of the tooltip to 2x height of the anchor  */
  max-height: calc(anchor-size(height) * 2);
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
anchor-size のデモ

デモのスクリーンショット。

ポップオーバーやダイアログなどの最上位レイヤ要素でアンカーを使用する

アンカーの配置は、popover などの最上位レイヤの要素で非常に効果的です。および <dialog>。これらの要素は DOM サブツリーの他の部分とは別のレイヤに配置されますが、アンカーの位置指定により、最上層にない要素をテザリングして戻したり、一緒にスクロールしたりできます。これは、階層化されたインターフェースにとって大きな利点です。

次の例では、ボタンを使用してツールチップのポップオーバーがトリガーされます。ボタンがアンカーで、ツールチップが配置された要素です。配置した要素は、他のアンカー要素と同様にスタイルを設定できます。この特定の例では、anchor-nameposition-anchor は、ボタンとツールチップのインライン スタイルです。各アンカーには一意のアンカー名が必要であるため、動的コンテンツを生成する場合は、インライン化する最も簡単な方法です。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
popover でアンカーを使用するデモ

デモのスクリーンショット。

@position-try でアンカーの位置を調整する

最初のアンカー位置を取得したら、アンカーがブロックの端に達したら、位置を調整できます。別のアンカー位置を作成するには、@position-try ディレクティブと position-try-options プロパティを使用します。

次の例では、メニューの右側にサブメニューが表示されます。メニューとサブメニューはトリガーボタンに固定されることが多いため、アンカー ポジショニング API とポップオーバー属性を併用すると効果的です。

このサブメニューの横方向に十分なスペースがない場合は、メニューの下に移動できます。そのためには、まず初期位置を設定します。

#submenu {
  position: absolute;
  position-anchor: --submenu;

  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
}

次に、@position-try を使用して代替のアンカー位置を設定します。

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

最後に、2 つを position-try-options で接続します。まとめると、次のようになります。

#submenu {
  position: absolute;
  position-anchor: --submenu;
  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
  */ connect with position-try options */
  position-try-options: --bottom;
}

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
popover でアンカーを使用するデモ

アンカー位置の自動切り替えのキーワード

上から下、左から右(または両方)に反転させるなど、基本的な調整を行っている場合は、カスタムの @position-try 宣言を作成する手順を省略して、flip-blockflip-inline のようなブラウザ対応の組み込みの切り替えキーワードを使用することもできます。これらはカスタムの @position-try 宣言の代用として機能し、組み合わせて使用できます。

position-try-options: flip-block, flip-inline, flip-block flip-inline;

キーワードを反転することで、アンカーコードを大幅に簡素化できます。わずか数行で、さまざまな位置で完全に機能するアンカーを作成できます。

#my-tooltip {
  position-anchor: --question-mark;
  inset-area: top;
  position-try-options: flip-block;
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
position-try-options: flip-block で自動切り替えを使用する

position-visibility(サブスクローラー内のアンカー用)

場合によっては、ページのサブスクローラー内に要素を固定する必要があります。そのような場合は、position-visibility を使用してアンカーの表示 / 非表示を制御できます。アンカーはいつ固定されますか?いつ利用できなくなりますか?この機能では、これらのオプションを制御できます。position-visibility: anchors-visible は、アンカーがビューの外に出るまで配置された要素をビュー内に残すために使用します。

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
position-visibility: anchors-visible デモ

または、position-visibility: no-overflow を使用して、アンカーがコンテナからオーバーフローしないようにします。

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">で確認できます。
position-visibility: no-overflow デモ

特徴検出とポリフィル

現在、ブラウザのサポートは制限されているため、この API を使用する場合は注意が必要です。まず、@supports 機能クエリを使用して、CSS で直接サポート状況を確認できます。そのためには、アンカー スタイルを次のようにラップします。

@supports (anchor-name: --myanchor) {

  /* Anchor styles here */

}

さらに、Oddbird の CSS アンカー位置指定ポリフィルを使用してアンカー配置機能をポリフィルすることもできます。これは Firefox 54、Chrome 51、Edge 79、Safari 10 で動作します。このポリフィルは、基本的なアンカー位置機能のほとんどをサポートしていますが、現在の実装は完全ではなく、古い構文が含まれています。unpkg リンクを使用するか、パッケージ マネージャーに直接インポートできます。

アクセシビリティに関する注意事項

アンカー ポジショニング API を使用すると、要素を他の要素に対して相対的に配置できますが、本質的に意味のある関係が構築されるわけではありません。アンカー要素と配置された要素の間に実際にセマンティック関係がある場合(たとえば、配置された要素がアンカー テキストに関するサイドバー コメントである場合)、そのための 1 つの方法は、アンカー要素から配置された要素を指すように aria-details を使用することです。スクリーン リーダー ソフトウェアは、Aria の詳細を処理する方法をまだ学習中ですが、サポートは改善中です。

<div class="anchor" aria-details="sidebar-comment">Main content</div>
<div class="positioned" id="sidebar-comment">Sidebar content</div>
.anchor {
  anchor-name: --anchor;
}

.positioned {
  position: fixed;
  position-anchor: --anchor;
}

popover 属性または <dialog> 要素でアンカーの位置指定を使用している場合、適切なアクセシビリティのためにブラウザがフォーカス ナビゲーションの修正を処理するため、ポップオーバーやダイアログを DOM 順にする必要はありません。詳しくは、仕様のユーザー補助機能に関する注記をご覧ください。

まとめ

これはまったく新しい機能であり、皆様がこの機能を使って何を作成されるかを楽しみにしています。これまでに、グラフの動的ラベル、コネクタ線、脚注、視覚的な相互参照など、コミュニティで優れたユースケースをいくつか見てきました。アンカーの位置付けをテストされている間、ぜひフィードバックをお寄せください。バグを見つけた場合は、お知らせください

関連情報