https://www.jonoalderson.com/conjecture/its-time-for-modern-css-to-kill-the-spa/
[jono-alderson]
Jono Alderson
Independent technical SEO consultant
[ ] Menu
* Home
* About
* Speaking & Events
* Consulting
* Blog
* Recommendations
+ Tech & Tools
+ Books
* Contact
It's time for modern CSS to kill the SPA
24th July, 2025
[32defd3f59a0]
[file_00000000be4861f49d1f8af54cec64de]
Native CSS transitions have quietly killed the strongest argument for
client-side routing. Yet people keep building terrible apps instead
of performant websites.
The app-like fallacy
"Make it feel like an app."
At some point during the scoping process, someone says the words.
A CMO. A digital lead. A brand manager. And with that single phrase,
the architecture is locked in: it'll be an SPA. Probably React. Maybe
Vue. Almost certainly deployed on Vercel or Netlify, bundled with
a headless CMS and a GraphQL API for good measure.
But the decision wasn't really about architecture. It wasn't even
about performance, scalability, or content management. It was about
interactions. About how the site would feel when you click around.
The assumption was simple: Seamless navigation requires us to build
an app.
That assumption is now obsolete.
The false promise of SPAs
The reason SPAs became the default wasn't because they were better.
It was because, for a while, they were the only way to deliver
something that felt fluid - something that didn't flash white between
pages or jank the scroll position.
But here's the uncomfortable truth: most SPAs don't actually deliver
the polish they promise.
What you usually get is:
* A page transition that looks smooth, until you realise it's just
fading between two loading states
* Broken scroll restoration
* Inconsistent focus behaviour
* Delayed navigation while scripts rehydrate components
* Layout shift, content popping, or full-page skeletons
* A performance hit that's entirely disproportionate to the effect
This isn't theoretical. Look at most sites built with Next.js,
Gatsby, or Nuxt. They're shipping kilobytes (often megabytes) of
JavaScript just to fake native navigation. Routing logic, hydration
code, loading spinners - all just to stitch together something that
browsers already knew how to do natively.
Instead of smoothness, you get simulation. And instead of a fast,
stable, SEO-friendly experience, you get a heavy JavaScript machine
trying to recreate the native behaviour we threw away.
We've been adding mountains of JS to "feel" fast, while making
everything slower.
An aside - I went deeper on this in JavaScript broke the web,
where I outlined how our obsession with JS-first development is
actively eroding the web's foundations.
The web grew up
While we were busy reinventing navigation in JavaScript, the platform
quietly solved the problem.
Modern browsers - specifically Chromium-based ones like Chrome and
Edge - now support native, declarative page transitions. With the
View Transitions API, you can animate between two documents -
including full page navigations - without needing a single line of
JavaScript.
Yes, really.
What we're calling "modern CSS" here is shorthand for View
Transitions, Speculation Rules, and a return to native browser
features that were always designed to handle navigation, interaction,
and layout. These capabilities let us build rich, seamless
experiences - without rewriting the browser in JavaScript.
An aside - CSS is also declarative, resilient, expressive,
scalable, and increasingly intuitive. It's accessible to anyone
who can write plain HTML. And that structural clarity reinforces
everything I argued in Why semantic HTML still matters - that
clean, meaningful markup is the bedrock of performance,
maintainability, and machine readability.
That means you can:
* Fade between pages
* Animate shared elements (e.g. thumbnails - product detail)
* Maintain persistent elements like headers or navbars
* Do it all with real URLs, real page loads, and no JS routing
hacks
Let's make this concrete.
Basic cross-page fade transition
With just a few lines of CSS, you can trigger smooth visual
transitions between pages.
On both the current and destination page, add:
@view-transition {
navigation: auto;
}
::view-transition-old(root),
::view-transition-new(root) {
animation: fade 0.3s ease both;
}
@keyframes fade {
from { opacity: 0; }
to { opacity: 1; }
}
That's it. The browser handles the transition - no client-side
routing, no hydration, no loading spinners.
Shared element transitions
Want to animate a thumbnail image into its full-size product
counterpart on the next page?
No JavaScript needed - just assign the same view-transition-name to
the element on both pages:
On the product listing page:
On the product detail page:
The browser matches and animates the elements between navigations.
You can animate position, scale, opacity, layout - all with CSS.
But what if I need JS-driven transitions?
You can manually trigger transitions inside a page too:
document.startViewTransition(() => {
document.body.classList.toggle('dark-mode');
});
Perfect for things like tab toggles or theme switches -- without
needing a framework or hydration layer.
Speculation rules: instant navigation without JS
View Transitions make things smooth. But what about fast?
That's where Speculation Rules come in. This lets the browser preload
or prerender full pages based on user behaviour - like hovering or
touching a link - before they click.
The result? Navigation that's instant. No waiting. No loading. No
spinners.
[?][?] A Note of Caution
Speculation Rules are a performance multiplier. On a lean site, they
make things feel instant. But if your pages are slow, bloated, or
JS-heavy, speculation just front-loads those costs.
If your site is bloated, speculation will still speculate - and the
user pays the price.
That means wasted CPU, network bandwidth, and mobile battery - often
for pages the user never even visits.
Use them carefully. On a fast site, they're magic. On a slow one,
they're a trap.
Browsers want to help - if we let them
Modern browsers are smarter than ever. They're constantly looking for
ways to improve speed, responsiveness, and efficiency - but only if
we let them.
One of the clearest examples is the Back/Forward Cache (bfcache),
which allows entire pages to be snapshotted and restored instantly
when users navigate back or forward.
It's effectively free performance - but only for pages that behave.
That means no rogue JavaScript, no intercepted navigation, no
lifecycle chaos. Just clean, declarative architecture. Just HTML
and CSS.
Unsurprisingly, this plays beautifully with a well-structured,
multi-page site. But for most SPAs, it's a non-starter. The very
design patterns that define them - hijacked routing, client-side
rendering, complex state management - break the assumptions that
bfcache relies on.
This is a microcosm of a much bigger theme: browsers are evolving to
reward simplicity and resilience. They're building for the kind of
web we should have been embracing all along. And SPAs are
increasingly the odd ones out.
SPA vs MPA: a performance reality check
Average Next.js marketing site
+ JS bundle: 1 - 3MB
+ TTI: ~3.5 - 5s (depending on hydration strategy)
+ Route transitions: simulated
+ SEO: complex, fragile
+ Scroll/anchor behaviour: unreliable
Modern MPA + View Transitions + Speculation Rules
+ JS bundle: 0KB (optional enhancements only)
+ TTI: ~1s
+ Route transitions: real, native
+ SEO: trivial
+ Scroll/focus/history: browser-default and perfect
Modern CSS doesn't just replace SPA behaviour - it outperforms it.
Don't build a website like it's an app
Most websites aren't apps.
They don't need shared state. They don't need client-side routing.
They don't need interactive components on every screen. But somewhere
along the way, we stopped making the distinction.
Now we're building ecommerce stores, documentation portals, marketing
sites, and blogs using stacks designed for real-time collaborative
UIs. It's madness.
A homepage with six content blocks and a contact form doesn't need
hydration, suspense boundaries, and a rendering strategy.
It needs fast markup, clean URLs, and maybe - maybe - a bit of
interactivity layered on top.
And yet, on every project:
1. A stakeholder says, "make it feel like an app."
2. A dev team reaches for Next.js or Nuxt.
3. Routing goes client-side.
4. Performance falls off a cliff.
5. Now you need edge functions, streaming, ISR, loading strategies,
and a debugging plan.
6. And somehow... it still feels slower than a regular link click and
a CSS animation.
This isn't about being anti-framework. It's about being intentional.
Use React if you want. Use Tailwind, Vite, whatever. Just don't ship
it all to the browser unless you need to.
Build a site like a site. Use HTML. Use navigation. Use the platform.
It's faster, simpler, and better for everyone.
Build for the web we have
SPAs were a clever solution to a temporary limitation. But that
limitation no longer exists.
We now have:
* Native, declarative transitions between real pages
* Instantaneous prerendered navigation via Speculation Rules
* Graceful degradation
* Clean markup, fast loads, and real URLs
* A platform that wants to help - if we let it
If you're still building your site as an SPA for the sake of
"smoothness," you're solving a problem the browser already fixed -
and you're paying for it in complexity, performance, and
maintainability.
Use modern server rendering. Use actual pages. Animate with CSS.
Preload with intent. Ship less JavaScript.
Build like it's 2025 - not like you're trapped in a 2018 demo of
Gatsby.
You'll end up with faster sites, happier users, and fewer regrets.
guest
Label [ ]
[ ] Name*
[ ] Email*
[Post Comment]
guest
Label [ ]
[ ] Name*
[ ] Email*
[Post Comment]
0 Comments
Inline Feedbacks
View all comments
I'm speaking at...
SEOktoberfest / G50, 2025
2025-09-21 / 2025-09-26
Stanglwirt, Austria
seoktoberfest.net
Spotlight, 2025
2025-10-29
Amsterdam
spotlightconf.com
Recent blog posts...
[20250725_152851-rotated]
What the world's first factory can teach us about AI
25th July, 2025
[file_00000000aaf061faafa67952f692b]
Why Semantic HTML Still Matters
21st July, 2025
Hire me!
I'm an award-winning consultant, and I'm available for hire.
Ready to take your website's technical SEO, performance, or
structured data strategy to the next level?
Hire me as a consultant
Get in touch
Email: me@jonoalderson.com
* [twi]Visit my Twitter profile
* [bsk]Visit my Bluesky profile
* [lin]Visit my LinkedIn profile
(c) Copyright 2025 Applied Energistics LTD.
* Terms
* Privacy
* Cookies
* Contact
JonoAlderson.com is operated by Applied Energistics LTD - a company
registered in England and Wales (Company # 11681212), at 38 Jute
Road, York, YO26 5EN, United Kingdom
[ ] Insert