CSSアドベントカレンダー13日目の記事になります。
以前、ReactでTooltipを作った記事を書きましたが、今回はCSSのみで作ってみました。
Chrome for Developersのブログを読まれている方だとピンときたかと思いますが、アンカー付きコンテナクエリでの実装です。
参考の項目に貼った記事を、少しだけアレンジして自分でも実装してみた事を記事にしてみました。
アンカー付きコンテナクエリとは
Chrome 143で実装された機能です。
今までのアンカー位置指定の仕様のレベル 1だと、ツールチップをブラウザの位置によって移動させることはできましたが、「移動した」という事までは検知できていなかったため「デフォルト(上)の背景色は『黒』、もしツールチップが下に行ったら『赤』にしたい」みたいな事はできませんでした。
今回Chrome 143で実装されたアンカー付きコンテナクエリによって、スタイルも位置によって変更することが可能になりました。
実装してみる
Chrome for Developersのブログを参考に実際に書いてみました。
公式との差分は、hoverしたら表示されるかされないかの違いだけです。
<div style="padding: 20px;">
<button class="anchor-btn">
Anchor Element
</button>
<div class="tooltip">
Always visible tooltip
</div>
</div>
body {
display: grid;
height: 200vh;
margin: 2rem;
place-items: start center;
}
.anchor-btn {
anchor-name: --my-anchor;
margin-left: 50px;
padding: 10px 20px;
font-size: 16px;
margin-top: 90vh;
}
.tooltip {
position: fixed;
position-anchor: --my-anchor;
position-area: top;
margin-bottom: 10px;
/* 上に入り切らない場合、ブロック方向(縦)に反転させる */
position-try-fallbacks: flip-block;
/* --- ホバー表示のための設定 --- */
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
pointer-events: none;
background: #333;
color: white;
padding: 8px 12px;
border-radius: 4px;
container-type: anchored;
}
/* 3. ホバー時の動作(隣接セレクタを使用) */
.anchor-btn:hover + .tooltip {
opacity: 1;
visibility: visible;
}
/* 4. 矢印(三角形)のスタイルと自動切り替え */
.tooltip::before {
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
/* デフォルト(ツールチップが上にいる時)の矢印:下向き ▼ */
border-top-color: #333;
top: 100%;
bottom: auto;
}
/* 5. 新機能:フォールバック(反転)が発生したときのスタイル */
@container anchored(fallback: flip-block) {
.tooltip {
/* 反転時は下に表示されるので、マージンを上方向に切り替える */
margin-bottom: 0;
margin-top: 10px;
}
.tooltip::before {
/* 反転(ツールチップが下にいる時)の矢印:上向き ▲ */
border-top-color: transparent;
border-bottom-color: #333;
/* 矢印の位置をツールチップの上側に移動 */
top: auto;
bottom: 100%;
}
}
Chrome 143以降のブラウザで確認してください
See the Pen CSS Tooltip by Makoto Ogata (@makoto-ogata) on CodePen.
実際に書いてみたコードは上下のみですが、position-try-fallbacks: flip-inlineを使用すれば左右の方向もできそうですね。
参考