I will demonstrate Turbo Frames by building a simple gallery on our home page. Here's how the resulting page will look.
Let's get started. First, update the index.html
page's <main>
tag with the following HTML. Just copy and paste it, I'll explain what's going on soon. All I did is added an image and the link, and wrapped them in a <turbo-frame>
tag.
<main style="text-align: center;">
<h1>Gallery</h1>
<turbo-frame id="gallery">
<img src="images/ocean.jpeg" alt="Ocean" width="500" height="400">
<div>
<a href="/gallery/forest">Next (forest)</a>
</div>
</turbo-frame>
</main>
Then create a new folder named gallery
in the public
directory. It contains three HTML files named forest.html
, mountains.html
, and ocean.html
. Here's their content.
<!-- forest.html -->
<turbo-frame id="gallery">
<img src="images/forest.jpeg" alt="forest" width="500" height="400">
<div>
<a href="/gallery/mountains">Next (mountains)</a>
</div>
</turbo-frame>
<!-- mountains.html -->
<turbo-frame id="gallery">
<img src="images/mountains.jpeg" alt="Mountains" width="500" height="400">
<div>
<a href="/gallery/ocean">Next (ocean)</a>
</div>
</turbo-frame>
<!-- ocean.html -->
<turbo-frame id="gallery">
<img src="images/ocean.jpeg" alt="Ocean" width="500" height="400">
<div>
<a href="/gallery/forest">Next (forest)</a>
</div>
</turbo-frame>
I've also added three new images in the public/images
directory that I grabbed from the w3schools website (or you can also find them in this project's GitHub repository).
That's all needed for our image gallery. Clicking on the Next link updates the picture without reloading the page. Rest of the page, like the <header>
content doesn't change.
Wait, what just happened?
You may have noticed the new HTML element named <turbo-frame>
. It's a custom HTML element provided by Turbo. This element allows you to divide your website into independent components that need to be changed independently. Let's see how they work, in three simple steps:
Step one: Wrap the component in a turbo frame.
You wrap the section on the page that you want to update in response to link clicks or form submissions inside a <turbo-frame>
element and give it a sensible id
.
In our example, I only want to update the image and the link below it, so I wrapped it inside a turbo frame with the ID gallery
.
<header>
<!-- header content remains unchanged -->
</header>
<main style="text-align: center;">
<h1>Gallery</h1>
<turbo-frame id="gallery">
<img src="images/ocean.jpeg" alt="Ocean" width="500" height="400">
<div>
<a href="/gallery/forest">Next (forest)</a>
</div>
</turbo-frame>
</main>
Step two: Wrap the response in a Turbo Frame
Any HTML that you want to send from the server, you wrap it in a turbo frame and give it the same ID as the original component. This is how Turbo figures out which frame to update on the page.
For example, here is the forest page that contains the new image and the new link, both wrapped in a turbo frame with the ID gallery
.
<!-- forest.html -->
<turbo-frame id="gallery">
<img src="images/forest.jpeg" alt="forest" width="500" height="400">
<div>
<a href="/gallery/mountains">Next (mountains)</a>
</div>
</turbo-frame>
Step three: There's no step three ;)
When you click the link and the response from the server arrives, Turbo finds the <turbo-frame>
element with the matching ID, and replaces the current <turbo-frame>
element with the one from the response.
In the above example, when you click the Next button, the <turbo-frame id="gallery">
element on the index.html
page is replaced with the matching turbo frame element that arrives from the response. That's how the image + link is replaced with a new image + link.
It doesn't matter if the server provides a full HTML document, or just a fragment containing an updated version of the requested frame (like we do above), only that particular frame will be extracted from the response to replace the existing content.
You can have multiple <turbo-frame>
elements on the page. Each one should have its own, unique ID. That's how Turbo knows which frame to replace when the response arrives from the server.
However, keep in mind that at any given request-response cycle, only one Turbo Frame will be swapped. If you need to update multiple components on the site, you'll have to use Turbo Streams, which we'll explore next.