Turbo Frames - Loading Spinner

Display a loading spinner while a Turbo Frame is `busy` fetching content asynchronously

View Solution on Patreon
Turbo Frames - Loading Spinner

Premise

Asynchronously loading content via Turbo Frames sometimes comes with a user experience degradation because the frame doesn’t advertise its busy status, and/or becomes unresponsive.

Starting Point

We start with a quite simplistic page that has a bullet point navigation and a Turbo Frame for the contents:

<ul>
  <li><a href="/page1" data-turbo-frame="async-loader">Load Page 1</a></li>
  <li><a href="/page2" data-turbo-frame="async-loader">Load Page 2</a></li>
</ul>

<turbo-frame id="async-loader" src="/page1">
  >
</turbo-frame>

Observe that the links in the navigation point to the async-loader Turbo Frame, i.e. its src attribute is targeted.

The NodeJS backend is set up so that it returns page1.html and page2.html respectively:

https://stackblitz.com/edit/turbo-frames-loading-spinner?file=index.js%3AL12

These two pages contain just the Turbo frame to exchange:

<!-- page1.html -->
<turbo-frame id="async-loader"><span>Page 1 took 1 sec to load<span></turbo-frame>
<!-- page2.html -->
<turbo-frame id="async-loader">Page 2 took 2 sec to load</turbo-frame>

Challenge

To implement loading/busy feedback, use the <template> fragment supplied in the index page:

  <template data-frame-spinner-target="placeholder"
    >↻ Spinner, <em>can be any</em> <strong>HTML</strong></template
  >

https://stackblitz.com/edit/turbo-frames-loading-spinner?file=index.html%3AL46

The crucial point is to clone this fragment and insert it when the busy attribute appears, and remove it afterwards. For this we make use of a MutationObserver in a Stimulus controller. Thankfully useMutation from the Stimulus Use project makes this trivial. Insert the HTML swapping logic here:

Here’s a preview of the end result:

Tabbed Turbo Frame navigation with loading display

Teaser

There’s a way to make this work only with CSS if you don’t need any HTML in the “loading” display!

More from

Turbo Frames - Using External Forms
03 February 2026

Refer to external forms from within a Turbo Frame

Turbo Frames - Typeahead Validation
20 October 2025

Use "preflight" requests to validate a form before submitting it

Turbo Frames - Swiper with Autoplay and View Transitions
14 January 2025

Create an autoplaying swiper using view transitions and Turbo Frames

Cookies
essential