Three.js and WebGL: a complete overview of 3D on websites
What WebGL and Three.js are, when 3D on a site pays off and when it only adds weight: 8 areas, pros and cons, a comparison with Babylon.js, Spline and video, speed rules, WebGPU and code examples.
In short
WebGL is the browser’s interface to the graphics card, and Three.js is the most popular free library on top of it: it turns low-level graphics calls into a scene with a camera, lights, materials and models. Together they put real 3D on a page without plugins — product viewers and configurators, hero scenes, data visualisation, games and AR. The newer WebGPU standard is supported by Three.js too, and browser support for it keeps growing. The price of 3D is weight and battery: models must be compressed, scenes paused when off screen, weak devices and visitors who switched motion off get a lighter version.
Three.js and WebGL at a glance
The main facts about the standard and the library in one table.
- WebGL
- A Khronos Group standard: the browser’s access to the GPU; WebGL 2 is supported everywhere
- WebGPU
- The new generation: closer to modern graphics APIs, with computations on the GPU; support is growing
- Three.js
- A 3D library by Ricardo Cabello (mrdoob), 2010; MIT licence
- What it gives
- Scenes, cameras, lights, physically based materials, model loaders, post-processing
- Renderers
- WebGLRenderer and WebGPURenderer with automatic fallback to WebGL
- Model format
- glTF — “the JPEG of 3D”; compression with Draco or Meshopt, textures in KTX2
- Releases
- Roughly monthly, numbered by revision (r186 at the time of writing)
- With React
- React Three Fiber and drei — scenes as components
- Alternatives
- Babylon.js, PlayCanvas; for scenes without code — Spline
- Models are made in
- Blender and other 3D editors, then exported to glTF
What Three.js is used for: 8 areas
3D earns its weight where it shows what a picture cannot.
-
01
Product in 3D
Turn, zoom and see from every side — before buying.
-
02
Configurators
Colour, material, size — the model changes in real time.
-
03
Hero scenes
Launches and premium brands that need to be remembered.
-
04
Data visualisation
Thousands of points, globes and networks that 2D cannot hold.
-
05
Real estate and interiors
Walking through a flat or an office before it is built.
-
06
Games and promo
Small games in the browser without installation.
-
07
AR and VR
WebXR puts the model into the room through the phone camera.
-
08
Interfaces with depth
Light 3D accents in an interface where they help understanding.
Pros and cons of Three.js
Three.js makes 3D accessible, but it does not make it free: every scene costs bytes and battery.
Pros · 8
-
Real 3D without plugins
Works in every modern browser on phones and computers.
-
A friendly level of abstraction
A scene, a camera and a mesh instead of hundreds of lines of raw graphics code.
-
Huge community
Thousands of examples, answers and ready effects.
-
glTF and good loaders
Models from Blender arrive with materials and animations.
-
Physically based materials
Metal, wood and glass look believable under any light.
-
Ready for WebGPU
The same scene can render through WebGPU and fall back to WebGL.
-
Works with React
React Three Fiber turns scenes into components.
-
Free
MIT licence, no royalties for commercial use.
Cons · 8
-
Weight
The library plus models and textures — megabytes if not compressed.
-
Battery and heat
A scene drawn 60 times a second works the GPU constantly.
-
Weak devices
Old phones stutter on heavy effects — a lighter version is needed.
-
Invisible to search
What is drawn on a canvas is not text: the content must be in the HTML too.
-
A frequently changing API
Monthly releases sometimes rename and remove things — upgrades need care.
-
Needs 3D skills
Good scenes need modelling, light and shaders, not only code.
-
Accessibility
Screen readers do not see a canvas; keyboard control is written by hand.
-
Not a game engine
Physics, editor and game logic come from other tools.
Three.js compared with Babylon.js, PlayCanvas, Spline and video
Ways to put 3D on a page, from code to a pre-rendered clip.
| Criterion | Three.js | Babylon.js | PlayCanvas | Spline | Video |
|---|---|---|---|---|---|
| What it is | a 3D library | a 3D engine | an engine with an editor | a design tool | a pre-rendered clip |
| Interactivity | full | full | full | basic | none |
| Flexibility | the highest | high | high | within the tool | none |
| Weight | medium | larger | medium | medium | depends on the file |
| Who builds it | a developer | a developer | a developer with an editor | a designer | a 3D artist |
| Best for | custom scenes and product viewers | complex 3D apps and games | browser games and ads | quick decorative 3D | complex scenes without interaction |
When 3D on Three.js is worth it — and when not
Ten typical tasks with a verdict.
-
Viewing a product from every side
Best fit3D shows what photos cannot.
-
Configurator
Best fitCombinations change in real time instead of hundreds of renders.
-
Launch of a premium brand
Best fitA memorable first screen is worth its weight.
-
Visualisation of large data
Best fitThousands of objects are drawn by the GPU.
-
Background decoration
WorksOften a video or CSS gives the same effect lighter.
-
A complex scene without interaction
WorksA compressed video may be cheaper for the device.
-
A full game
WorksPossible, but an engine like Babylon.js or PlayCanvas gives more out of the box.
-
A corporate site “to look modern”
Pick another3D without a task adds weight and distracts.
-
An audience on weak phones
Pick anotherPhotos and a little motion work better.
-
Content that must be found in search
Pick anotherText belongs in the HTML, not on a canvas.
How to keep 3D fast: 8 rules
-
01
Compress models
Draco or Meshopt make glTF several times smaller.
-
02
Textures in KTX2
They stay compressed even in the GPU memory.
-
03
Limit the pixel ratio
Above 2x the eye sees no difference, and the GPU draws twice as much.
-
04
Draw only when visible
A scene off screen stops — the battery says thank you.
-
05
Load on demand
The library and the model load when the visitor reaches the block.
-
06
Fewer draw calls
Thousands of identical objects are drawn as one with InstancedMesh.
-
07
A picture first
A still image stands in place of the scene until it is ready — and for weak devices instead of it.
-
08
Respect reduced motion
If motion is switched off in the system, show one still frame.
The Three.js ecosystem: tools for common tasks
The library draws; models, compression and effects come from around it.
| Task | Tools |
|---|---|
| Modelling | Blender |
| Compressing glTF | gltf-transform, Draco, Meshopt |
| Textures | KTX2, Basis Universal |
| Scenes in React | React Three Fiber, drei |
| Post-processing | postprocessing, EffectComposer |
| Physics | Rapier, cannon-es |
| Animation timeline | Theatre.js |
| Debugging | lil-gui, Spector.js |
| AR and VR | WebXR |
Common mistakes with 3D on sites
-
A model straight from the editor
Tens of megabytes of uncompressed geometry and textures — the visitor leaves before it loads.
-
Endless rendering
A scene that draws even when nobody sees it heats the phone for nothing.
-
Text inside the scene
Neither search engines nor screen readers see it.
-
No fallback
If WebGL fails, the visitor sees an empty rectangle.
-
Forgotten resources
Geometries and textures that are not disposed eat GPU memory with every page change.
-
3D for the sake of 3D
If the scene does not explain or sell, it only adds weight.
What Three.js looks like: 3 examples
A minimal scene, a product viewer and drawing only while visible. Checked by TypeScript 7 with Three.js r186; the first and third run in Chromium.
A minimal scene
A rotating cube with light, a correct size on resize and a capped pixel ratio.
import * as THREE from 'three';
// a scene, a camera and a renderer: the three things every 3D page starts with
const canvas = document.querySelector<HTMLCanvasElement>('#scene')!;
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // above 2x the eye sees no difference, the GPU does
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(0, 1.2, 4);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0xe4ff4e, roughness: 0.4 }),
);
scene.add(cube, new THREE.HemisphereLight(0xffffff, 0x222222, 2.5));
function resize() {
const { clientWidth: w, clientHeight: h } = canvas;
renderer.setSize(w, h, false);
camera.aspect = w / h;
camera.updateProjectionMatrix();
}
window.addEventListener('resize', resize);
resize();
renderer.setAnimationLoop((time) => {
cube.rotation.y = time / 1000;
renderer.render(scene, camera);
});
A product viewer
A compressed glTF model that the visitor turns and zooms within set limits.
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// a product viewer: a compressed glTF model that the visitor can turn and zoom
export async function showProduct(canvas: HTMLCanvasElement, url: string) {
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
const scene = new THREE.Scene();
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 3));
const camera = new THREE.PerspectiveCamera(35, canvas.clientWidth / canvas.clientHeight, 0.1, 50);
camera.position.set(0, 0.6, 2.4);
const draco = new DRACOLoader().setDecoderPath('/draco/'); // the model is compressed several times over
const gltf = await new GLTFLoader().setDRACOLoader(draco).loadAsync(url);
scene.add(gltf.scene);
const controls = new OrbitControls(camera, canvas);
controls.enableDamping = true;
controls.minDistance = 1;
controls.maxDistance = 4;
renderer.setAnimationLoop(() => {
controls.update();
renderer.render(scene, camera);
});
return renderer;
}
Draw only while visible
Off screen the scene stops; with motion switched off — one still frame.
import type { WebGLRenderer } from 'three';
// a 3D scene should not drain the battery: draw only while it is visible
export function renderOnlyWhenVisible(
renderer: WebGLRenderer,
canvas: HTMLCanvasElement,
draw: (time: number) => void,
) {
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduced) {
draw(0); // motion is switched off in the system: one still frame
return;
}
new IntersectionObserver(([entry]) => {
renderer.setAnimationLoop(entry?.isIntersecting ? draw : null);
}).observe(canvas);
}
Questions about Three.js and WebGL
What is the difference between WebGL and Three.js?
WebGL is the browser’s low-level access to the GPU; Three.js is a library that turns it into scenes, cameras and models.
Will 3D work on phones?
Yes, if the scene is light: compressed models, a capped pixel ratio and a still version for weak devices.
Does 3D hurt SEO?
Not if the content stays in the HTML and the scene loads lazily without slowing the first screen.
Where do 3D models come from?
They are made in Blender or another editor, or prepared from the manufacturer’s CAD files, then exported to glTF and compressed.
What is WebGPU and do I need it?
The next-generation graphics standard. Three.js can use it with a fallback to WebGL, so a site works on any browser.
Three.js or Spline?
Spline is quick for decorative 3D made by a designer; Three.js gives full control over weight, interaction and logic.
Can Three.js be used with React?
Yes, through React Three Fiber: the scene is described with components.
Is a video better than 3D?
If there is no interaction — often yes. 3D wins when the visitor needs to turn, choose or explore.
Online form
3D for
your site
I build 3D scenes on Three.js where they are justified: product viewers, configurators and hero scenes — compressed models, a speed budget and a light version for weak devices. Tell me about the idea — I answer within one working day.