Make Responsive

If you've ever opened a Three.js scene on your phone and seen a stretched or squished mess, you know the pain. Your scene looks great on your full-screen monitor, but resize the window or pull it up on a phone — and suddenly everything's broken.
The fix is simple: you need to update the camera and renderer whenever the window (or your canvas container) changes size.
the basic resize handler
function resize() {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// Update the camera's aspect ratio so it doesn't stretch
camera.aspect = width / height;
camera.updateProjectionMatrix();
// Update the renderer size to match
renderer.setSize(width, height);
}
window.addEventListener('resize', resize);
That's it. Three things:
- Update the camera's aspect ratio —
width / heightso objects don't look squished - Tell the camera to recalculate —
camera.updateProjectionMatrix()applies the change - Resize the renderer —
renderer.setSize(width, height)matches the canvas to the container
using ResizeObserver (better for containers)
If your canvas is inside a container that might change size on its own (like a sidebar that expands, or a panel that resizes), window.addEventListener('resize', ...) won't catch it. That's where ResizeObserver comes in:
const observer = new ResizeObserver(resize);
observer.observe(canvas.parentElement);
// Cleanup when your component unmounts
return () => observer.disconnect();
This watches the canvas's parent element and fires your resize function whenever it changes size — no matter why.
cleaning up
If your scene lives inside a Svelte or React component, you need to remove the event listener when the component goes away, otherwise it keeps running invisibly:
// Using addEventListener
window.addEventListener('resize', resize);
// Cleanup
return () => window.removeEventListener('resize', resize);
// Using ResizeObserver
const observer = new ResizeObserver(resize);
observer.observe(canvas.parentElement);
// Cleanup
return () => observer.disconnect();
full example
// Create your scene, camera, renderer…
function resize() {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
resize(); // run once on load
window.addEventListener('resize', resize);
That's all you need. Your scene now adapts to any screen size.
