ツールチップやドロップダウン メニューを配置する際は、ページ上の別の要素を基準に配置することがよくあります。絶対位置指定を使用してこの効果を実現する方法はありましたが、より複雑な要件では、これまで JavaScript を使用してアイテムを配置していました。
CSS アンカー配置は、別の要素を基準として要素を宣言的に配置する方法を提供します。
テザリングの要素
要素をアンカーにするには、2 つのダッシュで始まる任意の文字列の anchor-name
値を指定します。これは、位置指定された要素がアンカーを見つけるために使用する識別子です。わかりやすい名前を付けると便利です。要素がさまざまな方法でアンカーとして使用される場合は、要素に複数のアンカー名を付けることもできます。
位置指定された要素をテザリングできるようにするには、いくつかのプロパティを設定する必要があります。まず、position: absolute
または position: fixed
を設定して、要素をドキュメントのフローから取り出し、フローティングさせます。
次に、position-anchor
をアンカーに設定したアンカー名に設定して、テザリングするアンカーを設定する必要があります。
最後に、アンカーの配置方法を設定する必要があります。position-area
については、このモジュールで後ほど詳しく説明します。
#anchor {
anchor-name: --my-anchor;
}
#positionedElement {
position: absolute;
position-anchor: --my-anchor;
position-area: end;
}
暗黙的なテザリング
ポップオーバーは、さらに簡単にテザーできます。popovertarget
を使用したボタンを使用するか、showPopover({source})
で source
を設定してポップオーバーを開くと、ポップオーバーにはすでに「暗黙的なアンカー」が設定されています。ポップオーバーはデフォルトで position: fixed
でフローティングされているため、ポップオーバーを配置するには、位置を設定するだけです。
#anchor{}
#positionedElement {
position-area: end;
margin: unset;
}
潜在的なアンカーのスコープ設定
アンカーの配置をコンポーネントの一部として実装すると、ドロップダウン メニューのようなパターンを複数の場所で使用できるようになります。同じ anchor-name
を複数回使用する場合、各配置要素が正しいアンカーを見つけるようにするにはどうすればよいですか?
JavaScript ソリューションでは、各アンカーに一意の ID を追加し、その ID を位置指定された要素から参照します。これは面倒なため、CSS には anchor-scope
を使用したよりシンプルなソリューションがあります。
anchor-scope
プロパティは、要素とその子孫の間でのみ一致するアンカー名を設定します。1 つ以上のアンカー名のリストまたはキーワード all
を受け取り、定義されたすべてのアンカー名のスコープを制限します。
anchor-scope
は、配置された要素とアンカー要素の両方の祖先で、同じ名前の他のアンカー要素を含まない要素に追加するのが理想的です。多くの場合、これは再利用可能なコンポーネントのルートにあります。
次の例は、同じ anchor-name
を持つ繰り返し要素に anchor-scope
を適用した場合の違いを示しています。この例では、すべての <img>
要素と画像バナーが --image
アンカー名を参照しています。anchor-scope
が <li>
要素に適用されている場合、position-anchor: --image
はバナーと同じ <li>
要素内の <img>
要素のみと一致します。それ以外の場合は、最後にレンダリングされた <img>
と一致します。
位置付け
要素をアンカーにテザリングしたので、次は要素を配置します。アンカー ポジショニングでは、position-area
と anchor()
関数の 2 つのポジショニング方法が用意されています。
position-area
position-area
プロパティを使用すると、1 つまたは 2 つのキーワードを指定して、アンカーの周囲に要素を配置できます。これは一般的なユースケースの多くをカバーしており、多くの場合、ここから始めるのが適切です。
position-area
の仕組み
position-area
は、アンカーと位置指定された要素の元の包含ブロックの端によって生成された領域に、位置指定された要素の新しい包含ブロックを作成することで機能します。
position-area
には多くのキーワードがありますが、わかりやすくするためにいくつかのカテゴリに分類できます。Anchor-tool.com は、構文を調べるのに最適なツールです。
物理キーワード
物理キーワード top
、left
、bottom
、right
、center
を使用できます。たとえば、position-area: top right
は、アンカーの右上にある配置された要素を配置します。これらのキーワードには、y-start
、x-start
、y-end
、x-end
という物理軸の同等物もあります。
論理キーワード
論理キーワード block-start
、block-end
、inline-start
、inline-end
を使用することもできます。たとえば、position-area: block-end inline-start
は、英語などの言語では、位置指定された要素をアンカーの下かつ左に配置します。ドキュメントの書き込みモードでは、ブロック軸のアンカーの後、インライン軸のアンカーの前に配置します。center
は論理キーワードとともに使用することもできます。
論理キーワードを指定する場合は、軸を省略することもできます。ブロック軸を最初に、インライン軸を 2 番目に指定します。position-area: start end
は position-area: block-start inline-end
と同じか、position-area: inline-end block-start
と同じです。
複数のグリッド領域にまたがる
これまでのところ、これらのオプションでは、配置された要素を単一のグリッド スペース内に配置することしかできません。物理プロパティまたは論理プロパティに span
接頭辞を追加すると、隣接する中央グリッド スペースが追加されます。position-area: span-top right
はアンカーの右側に配置され、アンカーの下から配置された要素の元のコンテナ ブロックの上まで配置されます。
プルダウン メニューの一般的な位置領域は position-area: block-end span-inline-end
です。
span-all
キーワードは 3 行または 3 列にまたがります。
単一のキーワード
キーワードを 1 つだけ設定すると、もう一方の軸は自動的に設定されます。この機能は、ほぼ想定どおりに動作しますが、その仕組みを理解しておくと役立つ場合があります。
指定されたキーワードで軸が明確に示されている場合、もう一方の軸は span-all
として計算されます。つまり、position-area: bottom
は position-area: bottom span-all
と同等であり、位置指定された要素はアンカーの下に配置され、包含ブロックの幅全体が使用可能になります。
一方、キーワードが軸を明確に示していない場合は、繰り返されます。position-area: start
は start start
と同等で、左から右に読む言語ではアンカーの左上に配置されます。
anchor()
関数
より高度なユースケースでは、position-area
が要件を満たさない場合があります。anchor()
関数を使用すると、別の要素の位置に基づいて個々のインセット プロパティを設定できます。これは CSS の長さに解決されるため、計算や他の CSS 関数で使用できます。また、異なる側面を異なるアンカーにテザーすることもできます。
anchor()
関数は、アンカー名とアンカーの側面を受け取ります。要素にデフォルトのアンカーがある場合(position-anchor
で設定されているか、ポップオーバーなどで暗黙的に設定されている場合)、アンカー名を省略できます。
.positionedElement {
block-start: anchor(--my-anchor start);
/* OR */
position-anchor: --my-anchor;
block-start: anchor(start);
}
フォールバック値
anchor()
関数のアンカーが見つからない場合、宣言全体が無効になります。これは、アンカーが位置指定された要素の後にレンダリングされる場合や、一致する anchor-name
を持つ要素がない場合に発生する可能性があります。この問題を処理するには、フォールバックの長さまたは割合を設定します。
.positionedElement {
block-start: anchor(--my-anchor, 100px)
}
上記の例では、位置指定された要素の左側の値は --focused-anchor
に固定されていますが、その anchor-name
は最初のボタンにカーソルが合わされているか、フォーカスされている場合にのみ存在します。anchor()
関数は長さに解決されるため、別のアンカーをフォールバックとして使用できます。フォールバックを指定しなかった場合、位置指定された要素は配置されません。
アンカー サイドのキーワード
アンカーの辺の値は、アンカーのどの辺を配置するかを選択します。position-area
と同様に、アンカーの辺の値はさまざまな構文タイプをサポートしています。
タイプ | 値 | 説明 |
---|---|---|
実機 | top 、left 、bottom 、right |
物理キーワードはアンカーの特定の辺に対応しますが、設定する位置指定要素のインセットと同じ軸でのみ使用できます。 たとえば、 |
側部 | inside 、outside |
たとえば、 |
論理 | start 、end 、self-start 、self-end |
論理キーワードは、 |
割合 | 0%~ 100% |
パーセンテージ値は、指定された軸上のアンカーの開始位置から終了位置までの軸に沿って、配置された要素を配置します。 |
この例は、指定された軸でパーセンテージ値が常に開始から終了に移動する方法を示しています。
anchor()
の使用
anchor()
は長さであるため、非常に柔軟です。max()
や calc()
などの CSS 関数を使用して値を操作できます。
制限事項として、インセット プロパティでしか anchor()
関数を使用できません。
上記の例では、開いている詳細パネルの背後に背景を追加しています。この背景は、別のパネルが開いたときにスムーズにアニメーション表示され、ホバーされた詳細パネルを含むように拡大されます。これを実現するために、min()
を使用して 2 つのアンカー間の短い方の長さを選択します。
#indicator{
/* Use the smaller of the 2 values: */
inset-block-start: min(
/* 1. The start side of the default anchor, which is the open `<details>` element */
anchor(start),
/* 2. The start side of the hovered `<details>` element. */
anchor(--hovered start,
/* If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used. */
var(calc(1px * infinity)))
);
}
この例では、calc()
を使用して、開いているパネルの周囲にインライン スペースを追加しています。
アンカーのサイズを使用する
anchor-size()
関数を使用して、アンカーのディメンションを配置された要素のサイズ、位置、マージンに使用することもできます。
anchor-size()
はアンカー名を取得するか、デフォルトのアンカーを使用します。デフォルトでは、使用されている軸のアンカーのサイズが使用されるため、width: anchor-size()
はアンカーの幅を返します。物理キーワード width
と height
、または論理キーワード block
、inline
、self-block
、self-inline
を使用して、目的の長さを指定することで、他の軸を使用することもできます。
オーバーフローの処理
プルダウン メニュー コンポーネントを作成し、アンカー ポジショニングを使用してプルダウン メニューを目的の場所に配置しました。しかし、メニューを画面の反対側に移動したり、ユーザー メニューに使用したりすると、ユーザー名が長すぎてメニューがはみ出してしまいます。突然、ドロップダウンが画面外に移動します。どうすればよいでしょうか。
CSS アンカー ポジショニングには、配置された要素がコンテナ ブロックの外に出た場合に、堅牢なフォールバック セットをすばやく構築できる組み込みシステムがあります。
フォールバック オプション
position-try-fallbacks
ルールは、フォールバック オプションのリストを受け取ります。デフォルトの位置がオーバーフローすると、オーバーフローしない位置が見つかるまで、各オプションが順番に試されます。
フォールバック オプションとして任意の position-area
値を使用できます。この例では、英語などの左から右への書き込みモードでは、配置された要素はアンカーの下部に配置され、中央と右の列にまたがります。オーバーフローした場合は、アンカーの下に配置され、左側の列と中央の列にまたがります。それもオーバーフローする場合は、オーバーフローしても位置がデフォルトの位置に戻ります。
.positioned-element {
position-area: block-end span-inline-end;
position-try-fallbacks: block-end span-inline-start;
}
一般的なフォールバック ケースを処理する flip-
キーワードもいくつかあります。flip-block
と flip-inline
は、ブロック軸とインライン軸で要素を反転させようとします。flip-block flip-inline
と組み合わせて、両方の軸を反転させることもできます。flip-start
値は、アンカーの開始コーナーから終了コーナーまでの対角線に沿って、配置された要素を反転させます。
@position-try
を使用してカスタムのフォールバック オプションを作成することもできます。これにより、余白や配置を設定したり、アンカーを変更したりできます。
@position-try --menu-below {
position-area: bottom span-right;
margin-top: 1em;
}
#positioned-element {
position-try: --menu-below;
}
flip-block
と flip-inline
を @position-try
フォールバック オプションに追加して、バリエーションを作成できます。
#positioned-element {
position-try: --menu-below, flip-inline --menu-below;
}
上記の例では、ブラウザは次の手順に沿って処理を進め、オーバーフローしない解決策が見つかった時点で停止します。
- 要素は
position-area: end
でアンカーの右下に配置されます。 - オーバーフローした場合、要素は
--bottom-span-right
という名前のカスタム フォールバック オプションで配置されます。このオプションでは、要素はposition-area: bottom span-right
で配置され、下部に余白が追加されます。 - オーバーフローした場合、要素は
flip-inline --bottom-span-right
で配置されます。これは、カスタム フォールバック オプションとflip-inline
(実質的にはposition-area: bottom span-left
)を組み合わせたものです。 - オーバーフローした場合、要素は
--use-alternate
カスタム フォールバック オプションを使用して配置されます。このオプションでは、まったく異なるアンカーの下に要素が配置されます。 - オーバーフローした場合、要素は
position-area: end
を伴って元の配置に戻ります。これはオーバーフローすることがわかっている場合でも同様です。
フォールバック順序
デフォルトでは、初期位置がオーバーフローすると、ブラウザはオーバーフローしない位置が見つかるまで position-try-fallbacks
の各オプションを試します。position-try-order
を使用してこの動作をオーバーライドし、各フォールバック オプションをテストして、指定された軸で最もスペースの大きいオプションを使用できます。
軸は、論理キーワード most-block-size
と most-inline-size
、または物理キーワード most-height
と most-width
のいずれかで指定できます。
position-try-order
と position-try-fallbacks
は position-try
の短縮形と組み合わせることができ、その場合は順序が先になります。
スクロール
ユーザーは、スクロールしたときにページがスムーズに移動することを期待しています。これを実現するため、ブラウザではスクロール時のアンカー位置の使用方法に制限が設けられています。
配置された要素を異なるスクロール コンテナ内のアンカーにテザーできますが、要素はアンカーの 1 つのスクロールに応じてのみ移動します。これがデフォルトのアンカーになります。これは、ポップオーバーの暗黙的なアンカーか、position-anchor
の値のいずれかです。
アンカーがビューからスクロールアウトしても、配置された要素は表示されたままになります。アンカーが非表示のときに位置指定された要素を非表示にするには、position-visibility: anchors-visible
を設定します。これは、アンカーがオーバースクロールされた場合だけでなく、visibility: hidden
などで非表示になっている場合にも適用されます。
理解度を確認する
anchor()
の side の有効な値はどれですか?
inside
25%
25px
25px
などの長さはフォールバック値として使用できますが、サイドにはパーセンテージのみを使用できます。block-start
start
position-area
の有効な値はどれですか?
top
block-end inline-end
block-start block-end
どのプロパティが anchor()
関数をサポートしていますか?
top
margin-left
inset-block-start
transform
同じ anchor-name
を持つアンカーが複数ある場合はどうなりますか?