npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

three-html-elements

v0.1.0

Published

Place HTML elements in 3D space with Three.js - a lightweight library for integrating HTML content in WebGL scenes

Readme

Three HTML Elements

Place HTML elements in 3D space with Three.js - a lightweight library for integrating HTML content in WebGL scenes.

Features

  • Place HTML elements in 3D space with Three.js
  • Multiple positioning modes:
    • Standard mode: Simple CSS positioning
    • Transform mode: Full CSS 3D transforms using matrix3d
    • Billboard mode: Always face the camera
  • Occlusion: HTML elements can be hidden when behind 3D objects
  • Distance-based scaling: Scale HTML elements based on distance from camera
  • Full TypeScript support
  • Three.js API design pattern

Installation

npm install three-html-elements

Basic Usage

import * as THREE from 'three'
import { HTMLElement3D, HTMLRenderer } from 'three-html-elements'

// Set up Three.js scene
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5

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

// Create HTML renderer
const htmlRenderer = new HTMLRenderer(renderer)

// Create HTML element
const htmlElement = new HTMLElement3D({
  html: '<div style="padding: 10px; background-color: rgba(0,0,0,0.7); color: white;">Hello Three.js!</div>',
  position: [0, 1, 0],
  center: true,
  occlude: true,
  distanceFactor: 10
})

// Add to scene
scene.add(htmlElement)

// Animation loop
function animate() {
  requestAnimationFrame(animate)
  
  // Render Three.js scene
  renderer.render(scene, camera)
  
  // Render HTML elements
  htmlRenderer.render(scene, camera)
}

animate()

API Reference

HTMLElement3D

new HTMLElement3D(parameters: HTMLElement3DParameters)

Parameters

| Name | Type | Default | Description | |------|------|---------|-------------| | html | HTMLElement \| string | (required) | HTML element or HTML string to display | | position | THREE.Vector3 \| [number, number, number] | [0, 0, 0] | Initial position | | center | boolean | false | Center the element at its position | | occlude | boolean \| Object3D[] | false | Hide when behind other objects, can specify which objects | | transform | boolean | false | Use CSS matrix3d transforms | | sprite | boolean | false | Always face the camera (billboard) | | distanceFactor | number | undefined | Scale based on distance from camera | | zIndexRange | [number, number] | undefined | Z-index range [max, min] based on distance | | portal | HTMLElement | document.body | Parent element to append to | | as | keyof HTMLElementTagNameMap | 'div' | Element type for the wrapper | | wrapperClass | string | undefined | Class name for the wrapper element | | prepend | boolean | false | Project content behind the canvas | | fullscreen | boolean | false | Align to the upper-left corner and fill screen | | calculatePosition | Function | undefined | Custom position calculation function | | onOcclude | (hidden: boolean) => void | undefined | Callback when visibility changes |

Properties

All properties from THREE.Object3D, plus:

| Name | Type | Description | |------|------|-------------| | domElement | HTMLElement | The DOM element container | | contentElement | HTMLElement | The actual HTML content | | center | boolean | Whether element is centered | | occlude | boolean \| Object3D[] | Whether element is occluded by objects | | transform | boolean | Whether using CSS transform mode | | sprite | boolean | Whether element acts as a billboard | | distanceFactor | number \| undefined | Distance-based scaling factor | | zIndexRange | [number, number] \| undefined | Z-index range | | prepend | boolean | Whether content is behind the canvas | | fullscreen | boolean | Whether element fills the screen | | calculatePosition | Function \| undefined | Custom position calculation function | | onOcclude | Function \| undefined | Visibility change callback |

Methods

All methods from THREE.Object3D, plus:

| Name | Returns | Description | |------|---------|-------------| | dispose() | void | Remove the element from DOM and clean up resources | | updateOcclusionState(hidden: boolean) | void | Update occlusion state and trigger callback |

HTMLRenderer

new HTMLRenderer(renderer: THREE.WebGLRenderer, parameters?: HTMLRendererParameters)

Parameters

| Name | Type | Default | Description | |------|------|---------|-------------| | renderer | THREE.WebGLRenderer | (required) | The WebGL renderer | | domElement | HTMLElement | document.body | Container element for HTML | | frustumCulling | boolean | true | Enable view frustum culling | | positionThreshold | number | 1 | Minimum movement threshold to update position |

Methods

| Name | Parameters | Returns | Description | |------|------------|---------|-------------| | render | scene: THREE.Scene, camera: THREE.Camera | void | Render HTML elements in the scene | | dispose | | void | Clean up resources |

Examples

See the examples directory for working examples:

  • Basic: Simple HTML elements in 3D space
  • Transform: Demonstrating different transform modes
  • Occlusion: HTML elements that hide behind 3D objects
  • Interactive: Interactive HTML elements that control 3D objects

Advanced Usage

Custom Element Types

You can use any HTML element as the wrapper instead of the default div:

const htmlElement = new HTMLElement3D({
  html: '<p>Hello world</p>',
  as: 'section',
  wrapperClass: 'my-section-wrapper'
})

Selective Occlusion

You can specify which objects should occlude the HTML element:

const htmlElement = new HTMLElement3D({
  html: '<div>Behind the cube</div>',
  occlude: [myCube, mySphere],
  onOcclude: (hidden) => {
    console.log(`Element is ${hidden ? 'hidden' : 'visible'}`)
  }
})

Fullscreen and Prepend

// Create a fullscreen overlay behind the canvas
const overlay = new HTMLElement3D({
  html: '<div class="overlay">3D UI Overlay</div>',
  fullscreen: true,
  prepend: true
})

Custom Positioning

const htmlElement = new HTMLElement3D({
  html: '<div>Custom positioned</div>',
  calculatePosition: (object, camera, size) => {
    // Custom calculation logic
    return [x, y, zIndex] // Return array of coordinates
  }
})

Comparison with CSS3DRenderer

While Three.js provides CSS3DRenderer for placing HTML in 3D space, Three HTML Elements offers several advantages:

Advanced Features

  • Occlusion: HTML elements can be hidden when behind 3D objects
  • Distance Scaling: Scale elements based on distance from camera
  • Multiple Modes: Choose between simple positioning and full 3D transforms
  • Billboard Mode: Make elements always face the camera

Simple API

Three HTML Elements follows the standard Three.js patterns:

// Three.js style API integration
const scene = new THREE.Scene()
const htmlElement = new HTMLElement3D({ html: '<div>Hello</div>' })
scene.add(htmlElement)

// Rendering pattern matches Three.js
renderer.render(scene, camera)
htmlRenderer.render(scene, camera)

Performance Optimizations

  • Position threshold to reduce DOM updates
  • Frustum culling to skip elements outside the view
  • Optimized update loop

Implementation Details

Three HTML Elements is inspired by @react-three/drei's HTML component, but designed for vanilla Three.js projects. It:

  1. Extends THREE.Object3D for seamless scene graph integration
  2. Uses CSS transforms for proper 3D positioning
  3. Implements raycasting for occlusion detection
  4. Handles DOM lifecycle and cleanup automatically

License

MIT