View Transition API と htmx を組み合わせに成功
今年の3月くらいに「a-blog cms と View Transitions API で作るページ遷移のアニメーションの実装について」を書いていますが、少し進展したことから続編を書いてみようと思います。前回は、a-blog cms への実装について書いていましたが、今回は CMS 関係なく HTML + CSS + htmx ( JS ) というところでの万人に向けた内容になります。
View Transitions API との出会い
ICS MEDIA の「View Transitions API入門 - 連続性のある画面遷移アニメーションを実現するウェブの新技術」をご覧ください。これを読んで、そういうものがあるんだという事を知り、CMS のテンプレートに利用することを考えて、色々チャレンジしておりました。
私自身、JavaScript などが得意ではない中でも、HTML + CSS だけで実装する View Transitions API の画面遷移アニメーション、ICS MEDIA さんの中で MPA編 としては春時点では対応できておりました。しかし、SPA編の解説を読んでも、自分なりに実装することができず挫折しておりました。
htmx を利用した SPA な View Transitions API について
htmx を利用することで、基本的には JavaScript を書かずに、属性を書くだけで Ajax でコンテンツを更新ができるライブラリです。これと View Transitions API を組み合わせることで春に挫折したところをクリアすることができましたので書き残しておきます。
htmx の準備
<script src="https://unpkg.com/htmx.org@2.0.8"></script>
<script>
htmx.config.globalViewTransitions = true;
</script>CSS の準備
<style>
.vt-img {
contain: paint;
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
display: block;
}
::view-transition-group(root) {
animation-duration: 0.5s;
}
</style>大事なのは contain: paint; の設定です。
一覧ページの HTML サンプル
<div class="card">
<button
hx-get="detail-1.html"
hx-target="#main-area"
hx-swap="innerHTML transition:true"
hx-push-url="detail-1.html"
style="background: none; border: none; cursor: pointer; padding: 0;">
<img src="/images/detail-1.jpg"
class="vt-img"
style="view-transition-name: detail-1;"
alt="商品1">
<h3>サンプルタイトル1</h3>
</button>
</div>htmx の属性については説明を省き、View Transitions API の説明だけ書きますが、img に class="vt-img" を設定し、style="view-transition-name: detail-1;" で個別に名前を設定します。これが一覧と詳細で同じ名前のものが同じモノとして扱われます。
詳細ページの HTML サンプル
<div class="detail-container">
<button
hx-get="list.html"
hx-target="#main-area"
hx-swap="innerHTML transition:true"
hx-push-url="list.html">
← 一覧に戻る
</button>
<figure>
<img src="/images/detail-1.jpg"
class="vt-img"
style="view-transition-name: detail-1;"
loading="eager"
fetchpriority="high"
alt="詳細画像">
</figure>
<h1>サンプルタイトル1</h1>
<p>説明テキスト...</p>
</div>詳細ページでも、一覧と同じ class="vt-img" style="view-transition-name: detail-1;" の設定を行い、loading="lazy" させず、できるだけ早めに読み込んでくださいという意味で loading="eager" fetchpriority="high" としておきます。
以前は、view-transition-name: の設定を <head> に <style> で書かないといけないと思い、結構面倒なことをしていたのですが、<img> の中に style属性で書けばいい事がわかり実装が手軽になったと感じています。
大きな勘違いをしていました
ここまで実際のデモの HTML を実装しながら出来た気でいましたが、画像だけを拡大するアニメーションがつくように実装をしていましたという事でなく、見出しなどの要素についても同様にアニメーションさせる事ができる事が、ブログを書いている途中で気がつきました。
そういう事であれば、一覧の時と詳細ページでの表示の際には、アイキャッチ画像とタイトルの位置関係は変えないようなレイアウトの方がオススメという事になります。
一覧ページのタイトル
<h3 style="view-transition-name: title-1;">サンプルタイトル1</h3>詳細ページのタイトル
<h1 style="view-transition-name: title-1;">サンプルタイトル1</h1>カード全体の設定も可能でした
カードレイアウトであれば、そのカード自体に view-transition-name: を設定して、そのカード自体が詳細ページで大きくなるイメージであれば、カード全体の div に view-transition-name: を設定しておくことで同様に動かす事が可能でした。
この場合には、画像や見出しには、view-transition-name: をつける必要がなくなります。カードのレイアウトとしての画像と見出しの位置関係を、詳細ページにも同じであれば、全体で定義という実装がオススメです。
最後に
他の人が、読んでもよくわからないかもしれませんが、やっぱり書く事によって理解度が深まったのでヨシって事にします。 htmx + View Transitions API の組み合わせは、お手軽にいい感じの動きを付けられてイイ感じです。 今後、社内の案件でも普通に使っていきたいと思っています。
今回、SPA な View Transitions API を htmx を利用して実装してみました。 今回は静的な HTML で実装のデモを作ってみましたが、実際には、バックエンドに a-blog cms を利用することで詳細ページでリロードしても正しくコンテンツを出してくれたりするので、ぜひ htmx + View Transitions API のお供には a-blog cms の利用もご検討ください。
このブログも数日中には、Tailwind css + Alpine.js + htmx + View Transitions API + a-blog cms な感じのテーマに変更予定です。
