Rails: '読み込み中'アニメーションをTailwindCSSでTurbo Framesに追加する方法(翻訳)
プロジェクトで行き詰りを感じてしまった経験はおありですか?私はまさに最近そういう目にあいました。読み込みが遅いうえに、読み込み中であるサインを何も表示してくれないTurbo Framesのフレームがあったのです。私の混乱体験をお話いたします。
見ていてちょっと気が遠くなる[Histric transactions]タブの読み込み
🔗 Turbo Framesのbusy
属性
読み込み中の状態を表示する最も手軽な方法は、turbo_frame_tag
の内側にローダーを挿入することです。問題は、ローダーが動くのは最初の読み込みのときだけ、以後は新しいコンテンツの読み込みが完了するまで古いコンテンツが表示されてしまうことです。
ちょっと調べてみたところ、Turbo Framesには実はステートがあることを知りました。これは有用そうです。1つは読み込み中のbusy
で、もう1つは完了したときのcomplete
です。これらはHTML属性で表現されるので、適切なCSSセレクタを作成するのに使えます。
🔗 siblingセレクタ~
は便利
読み込み中アニメーションを作成するために、追加のコンテナでturbo_frame_tag
をラップしました。
<div class="relative min-h-96">
<%= turbo_frame_tag 'transactions', src: dashboard_transactions_historic_path do %>
<% end %>
</div>
オーバーレイを作成可能にするためにrelative
を追加し、高さを24rem以上にするためmin-h-96
を追加していましたが、上述のように、Loading...
は最初の読み込みしか表示されませんでした。このプロジェクトではトランザクション種別の切り替えを行っており、それぞれのパスが異なっているため、トランザクションを別の種別に切り替えると(この読み込みには時間がかかります)、古い表示が残り、UIには読み込み中であることが何も表示されません。
それでは変えてみましょう。
オーバーレイを作成するには、Turbo Framesのフレームのステートに基づいて振る舞いを変更する要素が別途必要です。これはturbo_frame_tag
の下に配置します。
<div class="relative min-h-96">
<%= turbo_frame_tag 'transactions', src: dashboard_transactions_historic_path do %>
Loading...
<% end %>
<div class="pointer-events-none absolute inset-0 z-20 flex items-center justify-center bg-gray-50 bg-opacity-25 backdrop-blur-sm transition-opacity">
<%= image_tag "loading.svg", class: "animate-pulse" %>
</div>
</div>
フレームのコンテンツを覆うオーバーレイには、現在はpulsating(脈動式)の読み込み画像が設定されています。このopacity(不透明度)を変更するにはセレクタを作成する必要があります。
そのためには、後続の兄弟要素を選択するsiblingセレクタ~
をTailwindの任意のバリアントと[[busy]~&]:
のように組み合わせます。込み入ったパズルになっていますが、[busy]
はフレームを指し、&
はローダーの要素を表すので、フレームがbusy
属性を取得すると、[[busy]~&]:
バリアントが効くようになります。ここにTailwindのopacityプロパティを併用します。opacityはデフォルトが0
で、バリアントがアクティブの場合は100
になります。以下のようにLoading...
テキストを削除することも可能です。
<div class="relative min-h-96">
<%= turbo_frame_tag 'transactions', src: dashboard_transactions_historic_path do %>
<% end %>
<div class="pointer-events-none absolute inset-0 z-20 flex items-center justify-center bg-gray-50 bg-opacity-25 opacity-0 [[busy]~&]:opacity-100 backdrop-blur-sm transition-opacity">
<%= image_tag "loading.svg", class: "animate-pulse" %>
</div>
</div>
これで、フレームのコンテンツが再読み込みされるたびに、読み込み中であることが表示されるようになります。JavaScriptは1行も書かず、プレーンなCSSセレクタだけでできました!
概要
元サイトの許諾を得て翻訳・公開いたします。
sibling(兄弟)は英ママとしました。
参考: 後続兄弟結合子 - CSS: カスケーディングスタイルシート | MDN