Graphics offset problem for high resolution canvas

To generate high-resolution images I’m using a very large canvas scaled with CSS. The problem is that the graphics are drawn offset. Raycasting intersections still trigger in the spot where the model should be, but the model itself is shown shifted to the top-right corner. The larger the canvas the larger the shift. There’s no shift for using render_width = canvas_container.clientWidth * window.devicePixelRatio, but any size over that increases the offset exponentially.

My canvas size is controlled by CSS:

max-width: 100% !important;
max-height: 100% !important;
width: unset !important;
height: unset !important;

The above rules were needed to override the automatic setting of whenever setting canvas.width (idem height).

I’m using the following (simplified, but still very long, sorry) function to set the size:

function set_sizes() {
	// viewport is the container element for the canvas
	const viewport_width = viewport.clientWidth * window.devicePixelRatio;
	const viewport_height = viewport.clientHeight * window.devicePixelRatio;
	const viewport_ar = viewport_width / viewport_height;

	if (params.maxQ) {
		if (image_ar > 1) {
			render_width = maxRenderSize; // = Math.min(renderer.capabilities.maxTextureSize, 8192)
			render_height = maxRenderSize / image_ar; // image_ar is a fixed aspect ratio
		} else if (image_ar < 1) {
			render_width = maxRenderSize * image_ar;
			render_height = maxRenderSize;
		} else {
			render_width = maxRenderSize;
			render_height = maxRenderSize;
	} else {
		if (image_ar > viewport_ar) {
			render_width = viewport_width;
			render_height = viewport_width / image_ar;
		} else if (image_ar < viewport_ar) {
			render_width = viewport_height * image_ar;
			render_height = viewport_height;
		} else {
			render_width = viewport_width;
			render_height = viewport_height;

	render_width = Math.round(render_width);
	render_height = Math.round(render_height);
	canvas.setAttribute('width', render_width);
	canvas.setAttribute('height', render_height);

	renderer.setSize(render_width, render_height);

	camera.aspect = image_ar;

	using_max_q = params.maxQ;
	need_render = true;

When disabling maxQ and thus setting a typical canvas size all works and renders okay. But when setting the canvas to high resolution the offset occurs.
I’m using intersectsObjects to add markers (spheres), which works fine at normal resolution. At maxQ the intersections trigger only for where the model should be, not where it’s drawn. The markers show up in the offset location. Setting the resolution to low again will show the markers in the right place on the model surface.

How can I fix this?