Skip to content


Lunchbox 2 contains:

  • Built-in components
  • Several automatically-registered ThreeJS components
  • The ability to add your own components via extend

Built-in components

<three-lunchbox> wrapper

The <three-lunchbox> wrapper handles several common use cases for ThreeJS scenes. It automatically creates a scene, WebGLRenderer, and camera, and adds a canvas to the DOM that stretches to fit its container.

Available attributes are:

NameDefault valueNotes
backgroundnullBackground color of the scene. Any ThreeJS color representation will work.

<three-lunchbox background="blue">
<three-lunchbox background="#0f0">
cameranullOptions to pass to the default camera. Accepts an object that is parsed and whose values are sent to the camera.

Nested values can be set by replacing dot notation with a dash.

Set camera.position.z to 5:
<three-renderer camera="{'position-z': 5}">

Set camera.position to 1, 2, 3:
<three-renderer camera="{'position': [1, 2, 3]}">
dprInfinityDevice pixel ratio. Will automatically adjust to the screen's DPR if set to Infinity.
dispatch-after-renderfalseSet to true to dispatch an afterrender CustomEvent after every render. See <three-lunchbox> events.
dispatch-before-renderfalseSet to true to dispatch a beforerender CustomEvent before every render. See <three-lunchbox> events.
manual-renderfalseSet to true to prevent automatic rendering. Note you'll need to call renderThree() yourself if this is the case.
renderernullOptions to pass to the default renderer. Accepts an object that is parsed and whose values are sent to the renderer. See camera for formatting.
scenenullOptions to pass to the default scene. Accepts an object that is parsed and whose values are sent to the scene. See camera for formatting.

The three property of <three-lunchbox>

A three-lunchbox component contains a property called three with ThreeJS details. For example:

const lunchbox = document.querySelector('three-lunchbox');

Current methods/properties of three are:

cameraThe component's camera.
rendererThe component's renderer.
sceneThe component's scene.

In TypeScript, you can get type completion by querying the ThreeLunchbox type:

import { type ThreeLunchbox } from 'lunchboxjs';
const lunchbox = document.querySelector<ThreeLunchbox>('three-lunchbox');

Other built-in <three-lunchbox> properties and methods

Other available properties and methods include:

renderThree(scene?, camera?)Manually render the default scene with the default camera. Optionally pass a custom override scene and camera.

TypeScript example:

import { type ThreeLunchbox } from 'lunchboxjs';
const lunchbox = document.querySelector<ThreeLunchbox>('three-lunchbox');
// manually render

Auto-registered components

All ThreeJS classes listed here can be used out of the box with Lunchbox 2. Elements must be separated by a dash if the class name is two or more words:

<!-- right -->

<!-- wrong -->

If the class name is one word, prepend three- to the element name:

<!-- right -->

<!-- wrong -->

See core concepts for attribute notes.

The instance property

All auto-registered components and components created by extend (see below) contain an instance property that holds the underlying ThreeJS object. For example:


const boxGeometry = document.querySelector('box-geometry');
console.log(boxGeometry.instance); // logs the BoxGeometry held by the component

In TypeScript, this you can get type completion with the Lunchbox generic type:

import { type Lunchbox } from 'lunchboxjs';
import * as THREE from 'three';

const boxGeometry = document.querySelector<Lunchbox<THREE.BoxGeometry>>('box-geometry');
console.log(boxGeometry?.instance); // logs the BoxGeometry held by the component

You can do anything with an instance that you would do with a standard ThreeJS object - for example:

const mesh = document.querySelector('three-mesh');
// add a child to the selected mesh
mesh.instance.add(new THREE.Mesh(
    new THREE.BoxGeometry(),
    new THREE.MeshBasicMaterial(),

This is a contrived example, since it would usually be easier to add a child via another <three-mesh> element; doing so also handles disposal automatically when removing the element from the DOM, while in the example above you would need to handle disposal manually.

Accessing instance is most useful when handling animations or large quantities of components/updates that would otherwise be expensive to add in the DOM.

Custom components via extend

You can add your own components via the extend command. For example, a common use case is to add OrbitControls:

import { extend } from 'lunchboxjs';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

extend('orbit-controls', OrbitControls);

Now you can add an <orbit-controls> component:

<three-lunchbox camera="{ 'position-z': 5 }">

    <orbit-controls args="[&quot;$camera$quot;, $quot;$domElement$quot;]"></orbit-controls>

TODO: $camera, $domElement docs