Render interactive HTML content onto 3D objects in Three.js with full CSS support, animations, and user interactions.
- 🎨 HTML to Texture - Render any HTML/CSS content as a texture on 3D meshes
- 🎬 CSS Animations - Full support for CSS animations and keyframes
- 📜 Scrolling Support - Handle scrollable content within textures
- 🖱️ Interactive Elements - Clickable buttons, links, and other HTML elements
- 📝 Text Selection - Select and copy text from 3D surfaces
- ⚡ Real-time Updates - Dynamic content updates reflected on 3D objects
This is an implementation for vanilla three.js projects. Check out the documented source code to see how it works and copy any relevant code.
The functionality is already built into threepipe and kite3d using plugins. Manual code integration is not required when using those frameworks.
If you are using React Three Fiber or any other framework, it needs to be ported separately, check documentation of those frameworks for guidance.
The library uses a combination of:
- CSS3DRenderer - Positions invisible HTML overlays aligned with 3D meshes for interaction
- HTML to SVG Conversion - Converts HTML content to SVG using
foreignObject - Canvas Texture - Renders the SVG to a canvas and creates a Three.js texture
This approach allows for:
- True CSS styling and animations
- Interactive HTML elements (buttons, links, forms)
- Text selection on 3D surfaces
- Scrollable content areas
npm installnpm run devnpm run buildnpm run previewimport { ThreeHtmlFiber } from './src/threeHtmlFiber.ts'
// Create the HTML renderer attached to a container
const threeHtmlFiber = new ThreeHtmlFiber(document.getElementById('container'))
// Optionally set page styles for consistent rendering
threeHtmlFiber.htmlRenderer.setPageStyles(yourCSSStyles)
// Add an object to render HTML onto
const cssObject = threeHtmlFiber.addObject(yourThreeMesh)
cssObject.element.innerHTML = '<div>Your HTML content here</div>'
cssObject.element.style.width = '1024px'
// In your animation loop
function animate() {
requestAnimationFrame(animate)
threeHtmlFiber.animate(camera)
// ... rest of your render logic
}Main class for managing HTML rendering on 3D objects.
new ThreeHtmlFiber(parentElement: HTMLElement)| Method | Description |
|---|---|
addObject(mesh, cssObject?) |
Attach HTML content to a Three.js mesh. Returns a CSS3DObject. |
render(camera) |
Manually trigger a render update (async). |
animate(camera) |
Queue-based render update for animation loops. |
| Property | Type | Description |
|---|---|---|
selectionOpacity |
number |
Opacity of the overlay when text is selected (default: 0.1) |
extraBorder |
number |
Border adjustment for texture sizing (default: 1.5) |
Handles the HTML-to-texture conversion.
| Method | Description |
|---|---|
update(node) |
Convert an HTML element to a CanvasTexture. |
setPageStyles(css) |
Set CSS styles to be included in the render. |
The included demo showcases:
- A glass-like dragon model with HTML content behind it
- Animated CSS spinners
- Wavy text animations
- Scrollable content
- Clickable buttons and links
- Gradient background with HTML content
- Multiple CSS animation examples (spinners, wavy text)
- Interactive button that tracks clicks
- Scrollable HTML area
- External links that open in new tabs
- Three.js - 3D rendering library
- ts-browser-helpers - HTML to SVG conversion utilities
- dat.gui - Debug GUI for the demo
- Vite - Build tool and dev server
Works in all modern browsers that support:
- WebGL
- CSS3DRenderer
- SVG foreignObject
- Canvas 2D
- Input elements (text fields, etc.) are not yet fully supported
- Complex CSS features may not render correctly in SVG foreignObject
- Performance depends on HTML complexity and update frequency
- External resources in HTML must be properly handled (CORS)
MIT
Contributions are welcome! Please feel free to submit a Pull Request.