How to resize canvas without resizing renderer or scaling contents?



Hi all,

I tried searching for an answer to this but didn’t find anything, hope I didn’t miss anything obvious. I also posted the question on SO before realising this forum existed :slight_smile:

I’d like to find an efficient way to resize the canvas to match the size of the browser window, without resizing or scaling the contents of the canvas – ie. if I’m displaying an object that takes up all of the viewport in fullscreen, when reducing the window it shouldn’t be entirely visible anymore.

Right, now, I’m doing this:
renderer.setSize(window.screen.width, window.screen.height)

Then, on init and resize:

camera.fov = window.innerHeight / window.screen.height;
camera.aspect = window.innerWidth / window.innerHeight;
renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);

Which works, but I’m just not sure it’s the proper way to do it. Mainly I’m concerned that it’s wasteful if the user is only ever using a tiny window – are all the contents of a full-size canvas still ‘computed’, or does setViewport avoid that?



First, you normally don’t change the field of view when resizing. Besides, calculating it like that seems strange. It’s normally a value like 40, 60, 70, something like that.

Even more important: If you don’t call camera.updateProjectionMatrix(), all your changes to camera properties have no effect.

I’m still not sure what you try to achieve. Can you show your code with a live example?


I’ll make a codepen in a moment. I am calling camera.updateProjectionMatrix(), I just didn’t mention it for tthe sake of clarity, my bad :smile:

The effect I want is basically the same as if you had a canvas with a fixed size that you didn’t resize at all, but I don’t want to render that even for users who use small windows.


Here is a codepen:

When you resize the window, the cube keeps the same size and stays centred. This is the wanted behaviour. I’m just wondering if I’m doing it the right way.


Can’t you use the following approach?

This is the default camera/rendering setup of the official three.js examples. Even if you resize, the cube keeps its size and stays centered. The thing is: It’s unusual to call WebGLRenderer.setViewport() since it’s automatically called by WebGLRenderer.setSize() with proper parameters. And you don’t have to worry about performance. Smaller windows means in general a lower resolution and therefore a performance benefit for fragment/pixel bound applications.


In your codepen, if you resize the window the cube does get resized too. It keeps it size relative to the size of the window; I would like the content to keep the same size relative to the size of the physical screen.

I do not at all fundamentally want or need to use .setSize(), it’s just that I found a solution that uses it, but I’m more than open about other solutions that do not.


I made a small graphic to explain what I’m trying to achieve and the reasoning behind my current implementation:


Okay, i see. Since i’ve never worked with such a setup, i can’t tell you if there are better ways to achieve the same result. Maybe somebody else of the community knows more.


No worries, thanks anyway! Hope someone else ran into the same thing and can provide some advice :slight_smile:


Just a quick post to say that a better approach, instead of setting the camera fov to window.innerHeight / window.screen.height, is to use this in order to keep a consistent size for objects at z=0 (hopefully this will make sense to at least some people):

camera.fov = Math.atan(window.innerHeight / 2 / camera.position.z) * 2 * THREE.Math.RAD2DEG;


We actually have a fiddle for this on our FAQ site :blush:. Maybe this helps:


Ah, cheers!
I’ll leave my project as it is for now since this approach seems fairly close to what I’m doing, so I don’t think I’m losing a lot (if at all) in terms of performance, and I’ll revisit this thread towards the end of development to see if I can change it up without breaking anything :stuck_out_tongue: