How to use OrbitControls with CSS2DRenderer

Hello, that is a topic about how to solve this problem. I got this problem a few hours ago and it was a bit annoying but finally I got why it was happening and I want to share this with you to save you time in the future.

First at all, if you don’t know what’s CSS2 it’s mostly used to render HTML elements on your 3D model using Three.js. It’s uses a pararell render that is CSS2 or CSS3 render

An example of both are here:

and this one for CSS3D

So following the topic of this article, when you set up your text on your 3D model

import { CSS2DRenderer, CSS2DObject } from '';

const textDiv = document.createElement( 'div' );
  textDiv.className = 'label';
  textDiv.textContent = "hehe"; = '-1em';
  const textLabel = new CSS2DObject( textDiv );
  textLabel.position.set( 0.1, 0.1, 0.1 );


  labelRenderer = new CSS2DRenderer(canvas);
  labelRenderer.setSize( window.innerWidth, window.innerHeight ); = 'absolute'; = '0px';

 document.body.appendChild( labelRenderer.domElement );

As you can see all the code is pretty easy, I use model.load whats is a gltf.scene casue I am using a GLTF file as 3D object.

One important thing to say is that you should put this code:

 document.body.appendChild( labelRenderer.domElement );

As it’s cause if not you won’t see your text, this is not for the 100% of cases, on mine I am using a canvas that have a fullscreen size.

And if you already had orbit controls settled on your last render as I had, your probabbly should had this code:

controls = new OrbitControls(camera, renderer.domElement);

At this point i was facing that my orbit control doesnt work, and that’s cause CSS2 render put another layer of render at the top of the layers so your orbit control what’s is charged on the renderer layer is unable to track your movements cause you are moving your mouse on the CSS2 render.

And how do you solve it?

In my case as I explained up in the article, was solved just changing the render where my orbit control tracks, this way:

controls = new OrbitControls(camera, labelRenderer.domElement);

And now it’s fully works as it used to do, but now I have the HTML div on my 3D model as I wanted.

I hope this was useful for anyone, and also thanks to the Three.js Community for help on other to release their projects using this brilliante library.


In both examples mentioned above when I zoom in, it’s not displaying a label.
Is there any method to disable the scaling factor for label on-camera zoom?

I think using = 'none'

Would be better, as it disables the events for the label layer, so returning things to what they were before.

Thanks, i was able to add text in my scene
but what if i want to add a shape instead, an animated circle svg. how should i do that