【CSS】@starting-style とpopover について

どうも、くまだです。

CSSの@starting-style とpopover についてのメモ。

popoverとは

popover は HTML 属性で、要素をトップレイヤー(ページの最前面の特別なレイヤー)に表示できる仕組みです。dialog のモーダル機能と似ていますが、より軽量で「クリックで開閉できる吹き出し」を作るのに向いています。

<button popovertarget="my-popover">開く</button>

<div id="my-popover" popover>
  <p>これが popover の中身です</p>
</div>

popover属性を付けた要素は最初 display: none の状態で隠れていて、popovertarget を持つボタンを押すと表示される——という挙動が JS なしで 動きます。

しかし、ふわっと表示させるには、これだけでは効きません。

opacityや transform は「途中の値」が計算できるプロパティなのでアニメできますが、display は none → block のように段階的に切り替わるプロパティ(discrete プロパティ)です。

discrete プロパティは、デフォルトでは「変化のたびに即座にスナップ」する挙動になっていて、transition が効きません。表示・非表示の切り替えと同時に他のプロパティのアニメが走ろうとしても、display: none が瞬時に効いて要素が消えてしまうため、見た目には何も起きないのです。

`opacity: 0` の状態から `opacity: 1` にアニメさせたいとき、**「開いた直後(display 切り替わり直後)に opacity が 0 だった」という開始状態**が必要です。

普通の transition は「いまの値 → 次の値」をつなぐ仕組みなので、「現れる直前の状態」をどこかで定義しなければアニメの起点が決まりません。

この2つを解決するのが、transition-behavior: allow-discreteと @starting-style です。

@starting-style とpopover

<button popovertarget="my-popover">開く</button>

<div id="my-popover" popover>
  <p>フワッと出てきます</p>
</div>
[popover] {
  /* 表示中のスタイル */
  opacity: 1;
  translate: 0 0;

  /* 2. transition-behavior でアニメさせるプロパティを指定 */
  transition:
    opacity 0.3s ease,
    translate 0.3s ease,
    display 0.3s allow-discrete,
    overlay 0.3s allow-discrete;
}

/* 1. 閉じている / 非表示状態のスタイル */
[popover]:not(:popover-open) {
  opacity: 0;
  translate: 0 -10px;
}

/* 3. @starting-style で「開く直前の開始スタイル」を定義 */
@starting-style {
  [popover]:popover-open {
    opacity: 0;
    translate: 0 -10px;
  }
}

/

See the Pen popover by kuma0605 (@kuma0605) on CodePen.

1. 閉じている状態(:not(:popover-open)):opacity: 0 で透明 + 少し上にズレている

2. 開く直前の開始スタイル(@starting-style 内):閉じている状態と同じ「透明 + 少し上」

3. 開いている状態(デフォルト):opacity: 1 で表示 + 元の位置

ボタンを押すと、要素が display: none から表示状態に切り替わる瞬間に 「いったん @starting-styleの値が適用」 → 「通常スタイルへ向けて transition」 という流れになります。

これで「開く瞬間にフワッと現れる」アニメが完成します。

ここまで読んでくださりありがとうございました。

この記事を書いた人