UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【CSS】view-transitionでスムーズなモーダル表現

view-transitionを使うとスムーズなモーダル表現ができることを知って調査した

developer.mozilla.org

詳細は以下の記事が参考になる ics.media

具体的には一覧のサムネイルをクリックすると、そのサムネイル画像が拡大し、モーダルの要素になるというものを作りたい

先に完成したものを見せると、このような感じ

一覧(id=list)にある要素のサムネイルが詳細(id=detail)のコンテンツの画像になる

実装

HTMLは以下のような感じで、詳細は最初hidden属性で非表示にしておく(display: noneでもよい)

  <div id="list">
    <div>
      <div style="width: 200px;">
        <img class="photo-item" style="width: 100%;" src="https://images.unsplash.com/5/unsplash-kitsune-4.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=dd060fe209b4a56733a1dcc9b5aea53a">
      </div>
      <button class="button">詳細をひらく</button>
    </div>
  </div>
  <div id="detail" hidden>
    <div style="width: 700px;">
      <img class="photo-detail" style="width: 100%;" src="https://images.unsplash.com/5/unsplash-kitsune-4.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjEyMDd9&s=dd060fe209b4a56733a1dcc9b5aea53a">
    </div>
    <div>詳細な説明</div>
  </div>

そして、CSSで繋げたい画像にview-transition-nameする

    .photo-item {
      view-transition-name: photo-example;
    }
    .photo-detail {
      view-transition-name: photo-example;
    }

JavaScriptではクリックしたら一覧と詳細のhiddenを入れ替えるようにする

    const buttonOpen = document.querySelector(".button");

    buttonOpen.addEventListener("click", () => {
      document.startViewTransition(() => {
        document.querySelector("#list").hidden = true;
        document.querySelector("#detail").hidden = false;
      });
    });

これだけで上のような表現ができた

アニメーションを設定する

デフォルトはopacityを0→1にするというアニメーションが設定されているが、これを変更することができる

例えば、速度を0.5sにしたい場合は以下

::view-transition-old(photo-example),
::view-transition-new(photo-example) {
  animation-duration: 0.5s;
}

定義したアニメーションを使うこともできる

   @keyframes grow-x {
    from {
      transform: scaleX(0);
    }
    to {
      transform: scaleX(1);
    }
  }

  @keyframes shrink-x {
    from {
      transform: scaleX(1);
    }
    to {
      transform: scaleX(0);
    }
  }

  ::view-transition-old(photo-example) {
    animation: 0.25s linear both shrink-x;
  }

  ::view-transition-new(photo-example) {
    animation: 0.25s 0.25s linear both grow-x;
  }

他参考

jhey ▲🐻🎈 on X: "Future CSS &amp;&amp; UI Tip! ⚡️ You could use View Transitions to create those word carousel-type effects 😍 span:nth-of-type(2) { view-transition-name: swap; } ::view-transition-old(swap) { animation-name: slide-down; } ::view-transition-new(swap) { animation-name: slide-up; }… https://t.co/X9HQh1J7j3" / X

https://codepen.io/jh3y/pen/mdaEJRG