<div> This is DOM content.</div>
body, html {
	background-color: #000;
	margin: 0px;
	overflow: hidden;
}

body {
    perspective: 800px;
}

canvas {
    display: block;
}

body, body > div {
    transform-style: preserve-3d;
}

div {
    width: 100px;
    height: 100px;
    background: pink;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    overflow: hidden;
}
import * as THREE from 'https://unpkg.com/three@0.116.1/build/three.module.js'
import {OrbitControls} from 'https://unpkg.com/three@0.116.1/examples/jsm/controls/OrbitControls.js'

const visibleHeightAtZDepth = ( depth, camera ) => {
  // vertical fov in radians
  const vFOV = camera.fov * Math.PI / 180;

  // Math.abs to ensure the result is always positive
  return 2 * Math.tan( vFOV / 2 ) * Math.abs( depth );
 };

const visibleWidthAtZDepth = ( depth, camera ) => {
  const height = visibleHeightAtZDepth( depth, camera );
  return height * camera.aspect;
};

// Simple three.js example

var mesh, renderer, scene, camera, controls;

var cameraZ = 20

init();
animate();

function init() {

    // renderer
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    // scene
    scene = new THREE.Scene();

    // camera
    camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.set( 0, 0, cameraZ );

    // controls
    controls = new OrbitControls( camera, document );

    // ambient
    scene.add( new THREE.AmbientLight( 0x222222 ) );

    // light
    var light = new THREE.DirectionalLight( 0xffffff, 1 );
    light.position.set( 0, 20, 0 );
    scene.add( light );
    
    var screenDepth
    console.log( '---: ', screenDepth = findScreenDepth( camera, renderer ) )

    // full width red rectangle at z = -100
    //const redGeom = new THREE.BoxBufferGeometry( visibleWidthAtZDepth( -100, camera), 1, 1 );
    const redGeom = new THREE.BoxBufferGeometry( 100, 100, 0.0001 );
    const redMat = new THREE.MeshBasicMaterial( { color: 'skyblue' } );
    const redMesh = new THREE.Mesh( redGeom, redMat );
    redMesh.position.set( 0, 0, - screenDepth + cameraZ );

    scene.add( redMesh, camera );

}

function findScreenDepth( camera, renderer ) {
    const { near, far } = camera
    const { height:physicalViewHeight } = renderer.getDrawingBufferSize()
    console.log( window.innerHeight, physicalViewHeight )
    const threshold = 0.00000000000001

    return _findScreenDepth( near, far )

    function _findScreenDepth( near, far ) {

        const midpoint = ( far - near ) / 2 + near
        const midpointHeight = visibleHeightAtZDepth( -midpoint, camera )

        if ( Math.abs( ( physicalViewHeight / midpointHeight ) - 1 ) <= threshold )
            return midpoint

        if ( physicalViewHeight < midpointHeight )
            return _findScreenDepth( near, midpoint )
        else if ( physicalViewHeight > midpointHeight )
            return _findScreenDepth( midpoint, far )
        else if ( midpointHeight == physicalViewHeight ) // almost never happens
            return midpoint
    }
}

function animate() {

    requestAnimationFrame( animate );

    //controls.update();

    renderer.render( scene, camera );

}
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.