view-transitionを使うとスムーズなモーダル表現ができることを知って調査した
詳細は以下の記事が参考になる 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; }