【CSS】CSSだけでTooltipを自動で画面内に表示できるようになるらしい

## はじめに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/f7f5c5c3-1f0b-db86-19d6-6ca0b644c893.png)

みなさんは、[CSS Anchor Positioning](https://drafts.csswg.org/css-anchor-position-1/)をご存知ですか？

[CSS Anchor Positioning](https://drafts.csswg.org/css-anchor-position-1/)は、まだ実験中の機能ですが、CSS Anchor Positioningを使うと、
特定の要素をAnchor（アンカー）として、tooltipなどの要素の位置を決めることができます。

この記事では、そんな[CSS Anchor Positioning](https://drafts.csswg.org/css-anchor-position-1/)を紹介しようと思います。

## CSS Anchor Positioningとは？
:::note warn
CSS Anchor Positioningは、まだ実験的な機能のため、Chrome Canaryの`chrome://flags`の`Experimental Web Platform features`を`Enabled`にしてください。
:::

CSS Anchor Positioningとは、特定の要素をAnchor（アンカー）として、
Anchor（アンカー）の要素を基準にtooltipなどの要素の位置を決めることができるものです。

### 基本的な使い方
#### 1. HTMLを記述する
まずは、Anchorとなる要素を`class="anchor"`とし、Anchorを基準として、位置を決める要素を`class="boat"`とします。

**wrapperとなる`<div>`はなくても大丈夫です。**

```sample.html
<div class="anchor">碇</div>
<div class="boat">ボート</div>
```

#### 2. Anchorを定義する
Anchorを定義するには、`anchor-name`というプロパティに `--name`の形で定義します。
Anchorを定義することで、`anchor()`関数を使うことができるようになります。

```sample.css
.anchor {
  anchor-name: --anchor;
}
```

また、HTMLで`anchor`属性を使うことでも定義することができます。
その場合は以下のように、`anchor`属性にAnchorにしたい要素のidを指定するだけです。
```sample.html
<div id="anchor" class="anchor">碇</div>
<div anchor="anchor" class="boat">ボート</div>
```

#### 3. Anchor()関数を使って要素を配置する

Anchor()関数は、3つの引数を受け取ることができます。

1. **Anchor要素**
    - 利用するAnchorの`anchor-name`の値を指定します。
    - 省略すると、htmlの`anchor`属性か、`anchor-default`のプロパティが使われます。
1. **位置**
    - `top`、`right`、`bottom`、`left`、`center`を指定します。
    - また、`%（パーセンテージ）`の指定や`calc()`を使って、位置を調整することもできます。
1. **フォールバック**
    1. オプションのフォールバック値で、長さやパーセンテージを指定します。

これらを使って、Anchorを基準に位置を決めます。

```sample.css
.boat {
  position: absolute;
  bottom: calc(anchor(--anchor top) + 16px);
  left: anchor(--anchor left);
}
```

↑上記のサンプルだと、
`.boat`のbottomの位置を`--anchor`のtopの位置から`+16px`の位置にし、
`.boat`のleftの位置を`--anchor`のleftの位置にする例です。

#### 4. スタイルを調整して完成
あとは、デザインを整えると完成です。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YzRaqXB" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/YzRaqXB">
  CSS Anchor Positioning - sample01</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

<font color="gray">*※ CSS Anchor Positioningは、まだ実験的な機能のため、Chrome Canaryの`chrome://flags`の`Experimental Web Platform features`を`Enabled`にしてご確認ください。*</font>

### 画面スクロールに合わせて、スクロースさせたい場合
```sample.html
<div class="container">
  <div class="anchor">碇</div>
</div>
<div class="boat">ボート</div>
```

上記のような構造で、Anchorとなる要素がスクロールされるコンテナの中にあり、Anchorを基準として位置を決める要素がコンテナの外にある場合、スクロールに合わせてAnchorを追跡する方法が必要あります。

その場合は、以下のように、`anchor-default`プロパティと`anchor-scroll`プロパティを使うことで、追従することができます。

`anchor-default`プロパティを使うことで、`anchor-name`で定義した子孫外の要素でも、アンカーに追従させることができます。

```sample.css
.boat {
    anchor-default: --anchor;
    anchor-scroll: --anchor;
}
```

#### サンプル

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="qBQYrjR" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/qBQYrjR">
  CSS Anchor Positioning - sample 02</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<font color="gray">*※ CSS Anchor Positioningは、まだ実験的な機能のため、Chrome Canaryの`chrome://flags`の`Experimental Web Platform features`を`Enabled`にしてご確認ください。*</font>


### アンカーの位置に合わせて、表示する場所を変える
[CSS Anchor Positioning](https://drafts.csswg.org/css-anchor-position-1/)が本領を発揮するのは、アンカーの位置に合わせて、表示させる場所を自動で決めてくれる機能を使う時です。

この機能を使うには、`position-fallback`プロパティを使って、フォールバックに基づいて、要素の位置を指定します。

では、実際にやって行きましょう。

#### 1. HTMLを記述する
Anchorを基準として位置を決める要素に`popover`属性を用いることで、アンカーの近くに表示することが可能になります。

```sample.html
<div class="anchor">碇</div>
<div class="boat" popover="manual">ボート</div>
```
<font color="gray">`popover`属性については、↓こちらの記事をご覧ください。</font>

https://qiita.com/degudegu2510/items/9fb31e7daeba8f328de3

#### 2.Anchorを定義する
`anchor-name`というプロパティを使って、Anchorを定義します。

```sample.css
.anchor {
  anchor-name: --anchor;
}
```

#### 3. アンカーの位置によって、表示する場所を変える
Anchorを基準として位置を決める要素に、`anchor-default`プロパティと`anchor-scroll`プロパティを指定し、追従するように記述します。

`position-fallback`プロパティに`--〇〇`の形でフォールバックで使用する`@position-fallback`を決めます。
そして、以下のように記述することで、アンカーの位置によって、表示する場所を変えることができるようになります。

<font color="gray">特定のブラウザでは、popover属性に`inset`の値が指定されているものがあるので、`inset: unset;`を指定してあげることで、うまくいくケースがあります。</font>

```sample.css
.boat {
  anchor-default: --anchor;
  anchor-scroll: --anchor;
  position-fallback: --fallback;
  inset: unset;
}

@position-fallback --fallback {
  @try {
    bottom: calc(anchor(top) + 16px);
    left: anchor(left);
  }
  @try {
    top: calc(anchor(bottom) + 16px);
    left: anchor(left);
  }
}
```

#### 4.popover属性を表示させる
popover属性は、デフォルトで非表示のため、popover属性を表示させるようにJavaScriptを以下のように記載します。

```sample.js
const POPS = document.querySelectorAll("[popover]");
POPS.forEach((POP) => POP.showPopover());
```

#### 5.スタイルを調整して完成
あとは、デザインを整えると完成です。

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="XWyENpZ" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/XWyENpZ">
  CSS Anchor Positioning - sample 03</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<font color="gray">*※ CSS Anchor Positioningは、まだ実験的な機能のため、Chrome Canaryの`chrome://flags`の`Experimental Web Platform features`を`Enabled`にしてご確認ください。*</font>


## まとめ
この記事では、まだ実験中の機能[CSS Anchor Positioning](https://drafts.csswg.org/css-anchor-position-1/)について紹介しました。

[CSS Anchor Positioning](https://drafts.csswg.org/css-anchor-position-1/)が実装されれば、TooltipなどのUIコンポーネントをもっと簡単に、アクセシビリティ意識した形で実装できそうです。


---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510