Is it possible to see HTML behind a canvas where Three.js is rendered?

I made a project, here’s the link to it.

I tried to do this because it’s needed for this mockup.
Here’s the link to the mockup - https://www.figma.com/design/qEiDTsGobLyugZeyD3ONdi/INSECA--APP-WEB?node-id=1806-4059&t=bMMpGIYJlHkIaRTr-0
Do you see the lens effect in the mockup? I wanted to replicate it. According to this mockup, HTML behind the lens must remain visible. That’s why there’s a blue circle behind the text, which should move unpredictably when scrolling. If it gets covered by the scene, it will look wrong.

Yes, it is possible. A Three.js canvas is just another HTML element, so you can control how it stacks with other elements using normal CSS.

If you want to see HTML behind the Three.js canvas, the canvas must be transparent and layered above the HTML content. In Three.js you can enable transparency like this when creating the renderer:

const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0x000000, 0);

Then in CSS you control the stacking order:

canvas {
position: absolute;
top: 0;
left: 0;
z-index: 2;
}

.background-html {
position: relative;
z-index: 1;
}

This allows the HTML to be visible behind the WebGL scene. Another common pattern is putting the canvas inside a container and using overflow and positioning to keep everything aligned during scroll.

If things move chaotically while scrolling, it is usually related to viewport units (like 100vh), mobile browser UI resizing, or the canvas being tied to scroll transforms. Using a fixed container or recalculating renderer size on resize/scroll can help stabilize it.

Here’s a small interactive example of a scene with a controller running in the browser if you want to see how layering and interaction can work in a Three.js environment:

https://theneoverse.web.app/#threeviewer&&controller

const renderer = new THREE.WebGLRenderer({ alpha: true });

and

renderer.setClearColor(0x000000, 0);

This code is already in my example - Vitejs - Vite (duplicated) - StackBlitz

canvas {
position: absolute;
top: 0;
left: 0;
z-index: 2;
}

.background-html {
position: relative;
z-index: 1;
}

This code doesn’t solve my problem. Adding this code doesn’t do anything.

Ideally, I want the lens to be transparent so I can see the HTML behind it. But right now I see a black lens.

In Three.js there is no issue having Three.js with transparent background over HTML content. For R3F I have no idea, because I do not use it.

https://codepen.io/boytchev/full/WbGMMrw

image

2 Likes

Thank you. Very interesting example. I replaced your model with my lens. And as I understand it, to get a real refraction effect, you need to use WebGLRenderTarget. But if you use it, there will be no transparency, so the HTML not will be visible behind. SThere are two ways: either follow your approach and add artificial aberrations and magnification, or change the web app’s design layout. Because again, in the layout, the blue area rotates when scrolling. And it’s located on a layer behind the text. And if this rotating area is obscured by the scene, result will look incorrect.

1 Like

Refraction needs knowledge about the back of the scene. If the HTML is just DOM-based, Three.js will not see it. Maybe you have to find a way how to grab an image of the HTML page and let Three.js use it as background.

Maybe this demo from the official R3F examples could be helpful:

https://codesandbox.io/p/sandbox/4j2q2

image

5 Likes