Turbo Morphing —A Cleaner Way to Update Your Rails UI
by Nived Hari, System Analyst

The Pain of Full‑Page Reloads
You make a change—maybe update some text or complete a task. You hit submit, and boom! The entire page reloads.
- Your scroll position? Gone.
- That form you meticulously filled out? Vanished into the void.
- Your patience? Hanging by a thread.

It’s 2025 and full‑page reloads still feel like dial‑up. Each time a page reloads the browser must:
- Download the entire HTML again.
- Reconstruct the DOM from scratch.
- Re-run all JavaScript and reload CSS.
Not only does this slow things down, but it also creates a frustrating user experience. Imagine an online store where every time you apply a filter, the entire page resets.
Turbo Streams to the Rescue … Mostly
Turbo Streams let us surgically update parts of the page. Need to add a comment? Send an <turbo-stream action="append" …>
.
They give precise control (append, prepend, update, remove, replace).
The trade‑off is boilerplate: for every element you touch you create a .turbo_stream.erb template and matching controller logic.
That duplication is perfectly fine when you need per‑element control—but it can feel heavy for everyday “just re‑render this section” cases.
Let’s take a simple app as an example.

In this app, there are two elements in play when an update happens:

If we were using Turbo Streams, we’d need to:
- ✅ Create multiple turbo_stream.erb templates for different elements.
- ✅ Write controller logic to handle updates for each element separately.
Here’s how that might look:

Looks fine… until your app grows and you need to update even more elements. Suddenly, you’re drowning in turbo_stream.erb templates.
There has to be a simpler way.
Enter Turbo Morphing 🚀
Turbo Morphing offers a lighter path. Instead of telling the browser how to change, you send fresh HTML for the section and let Turbo work out the minimal DOM patch.
<%= turbo_refreshes_with method: :morph, scroll: :preserve %>
One line in your application layout flips the switch. No extra templates. No new controller actions. Turbo compares the existing DOM against the new HTML using the Idiomorph library and morphs only what changed.
Idiomorph in a Nutshell
Idiomorph is a JavaScript library for intelligent, minimal DOM updates. Instead of replacing full elements, it compares the current DOM with the new version and updates only the parts that changed—preserving everything else.
- Smart diff‑and‑patch: updates only the nodes that differ.
- Preserves user state: text selections, cursor position, in‑flight form inputs stay intact.
- Keeps animations alive: because elements aren’t blown away.
- Tiny payload: no runtime virtual DOM; just an intelligent diff.
Morph vs. Streams—Choosing the Right Tool
You want… | Pick Turbo Streams | Pick Turbo Morph |
---|---|---|
Per‑element actions (append, prepend, etc.) | ✅ | - |
Multiple, disparate targets in one response | ✅ | ✅ |
Minimal code / templates | - | ✅ No extra files |
Keep user typing/scroll position | Requires Care | ✅ Built‑in |
Turbo Streams are precise tools. Morph is better for broad, simple updates. Use whichever fits your task.
Broadcasting & Real‑Time Goodness
Turbo Morphing also works seamlessly with Turbo Broadcasts. Broadcast a morphable partial and every subscribed client patches itself instantly—no templates needed.
Takeaways
- Not a replacement: Turbo Morphing complements Streams; it doesn’t supplant them.
- Less code, fewer templates: perfect when you just need the UI to stay in sync.
- Fallback to Streams: whenever you need explicit append/prepend semantics.
References
- Jorge Manrubia - Making a difference with Turbo - Rails World 2023
- 37signals Dev Blog – A Happier Happy Path in Turbo with Morphing
- Idiomorph Repository
- Hotwire Handbook
Here’s to smoother updates and cleaner code with Turbo Morphing. ✨