Design8 min read

Does Your Website Need 3D? An Honest Cost Breakdown

Three.js can make a site unforgettable or unusable. The difference is not taste — it is whether the experience is on the critical path. Here is how to have both.

I like WebGL. I have built scenes I am proud of. I also took the 3D city off my own homepage's default load, and the site got measurably better.

That is not a contradiction. It is the actual lesson, and it is worth explaining properly, because "add a 3D background" is one of the most expensive decisions a site can make without anyone noticing the invoice.

What 3D actually costs

The library is the smallest part.

Download. Three.js plus a React renderer and a helper library lands somewhere in the hundreds of kilobytes, compressed. On a good connection that is nothing. On a phone with two bars, that is seconds — and it competes with the fonts, the CSS, and the framework for the same bandwidth.

Parse and compile. Downloading is only step one. That JavaScript then has to be parsed and executed, on the main thread, before anything animates. On a mid-range Android device this is where the real delay lives, and it is invisible on the developer's laptop.

Continuous render cost. A 3D scene is not a static asset. It runs a render loop for as long as the page is open, competing with scrolling, with animation, with your form's input handling. This is the part that shows up as an unresponsive page and a bad INP score.

Battery and heat. On mobile, a continuously rendering WebGL canvas is a measurable drain. Visitors do not attribute it to your site. They just leave sooner.

Failure surface. Some devices have no WebGL. Some browsers block it. Some visitors have reduced-motion enabled at the OS level, and a swooping camera is precisely what that setting exists to prevent.

Add it up and the honest summary is: a 3D background on the critical path costs you your Largest Contentful Paint, some portion of your Interaction to Next Paint, and a slice of your mobile visitors. In exchange it gives you a first impression nobody forgets.

Sometimes that trade is right. Usually it is right in a narrower way than people implement it.

When 3D genuinely earns its place

When the 3D is the product. A configurator, a floor plan viewer, a game, a data visualisation you cannot express in two dimensions. Here the scene is the reason the page exists, and paying for it is not a trade-off, it is the point.

When the audience is not price-sensitive on load time. A campaign microsite that people arrive at from a conference talk, on desktop, on wifi, is a different context from a local service business's homepage arriving from a mobile search result.

When it is genuinely doing work. Showing a physical product from angles a photo cannot. Making a spatial relationship comprehensible. That is different from a field of drifting particles behind your headline.

When it does not

If a visitor's goal is to find out what you do, decide whether to trust you, and contact you — and your 3D scene makes each of those steps slower — then the scene is working against the page.

The uncomfortable question worth asking about any decorative 3D: if a visitor never saw it, would they be less likely to hire you?

Usually the answer is no. Which means it is costing you real performance for an impression that does not convert.

The approach I settled on: make it opt-in

There is a third option between "always on" and "cut it entirely," and it is better than both.

Keep the scene. Move it behind an explicit user action. Load nothing until someone asks for it.

On my own site the 3D city is still there — the whole thing, the buildings, the vehicles, the camera choreography tied to scroll. But the homepage does not load a single byte of Three.js until you find the trigger and click it. The trigger sits in the hero, disguised as an item in a list of technologies. Click "Three.js" and the city renders behind the page.

What this buys:

The initial load is clean. The heavy bundle is behind a dynamic import that only resolves on click. First paint is HTML, CSS, and a small amount of JavaScript.

The people who see it are the people who wanted it. Someone who clicks a hidden trigger is engaged. They are the audience the scene was always for.

It becomes a demonstration rather than decoration. A hidden interactive scene that a visitor discovers says something about capability that a permanent background does not. Anyone can put a WebGL background on a site. Choosing not to, and having it available anyway, is the more interesting signal.

Reduced-motion is a clean no. When the scene only mounts on request, honouring the reduced-motion preference is a single early return rather than a set of workarounds.

How to implement it without making a mess

A few implementation notes, since the details are where this goes wrong:

Code-split at the right boundary. The dynamic import has to sit above every 3D import, or the bundler pulls the library into the main chunk anyway. Verify by checking your build output, not by assuming.

Keep the state in context, not in the component that renders the canvas. The trigger and the canvas usually live in different parts of the tree. A small context provider is cleaner than lifting state through six components.

Mind your stacking context. A fixed-position canvas at z-index 0 that sits before an opaque element in the DOM will be painted over by that element's background and simply never appear. This wastes an hour if you have not hit it before.

Give people a way out. An exit control and an Escape key handler. A visitor who turned it on and now finds it distracting should not have to reload.

Have a default that stands on its own. If your design only looks good with the 3D running, you have not solved the problem, you have hidden it. A layered CSS gradient with a subtle grid costs nothing and gives a dark page real depth.

Persist the choice for the session. If someone turns it on and navigates, turning it back on for them is a small courtesy that makes the feature feel intentional.

The general principle

This applies well beyond 3D.

Any expensive experience — a video background, a heavy animation library, a canvas effect, an embedded map — should be evaluated on one question: is this on the path between the visitor arriving and the visitor acting?

If it is on that path, it has to be cheap. If it is not on that path, it can be as expensive as you like, as long as it loads only when someone asks for it.

The best version of a site is fast for everyone and impressive for anyone who goes looking. Those two goals are only in conflict if you load everything up front.

Working on something?

I can build this for you.

If any of the above matches a problem you're having, tell me about it. You'll get a straight answer on what I'd do and what it costs.

Or reach me directlyhello@ericjokl.com860 406 0262