HTMLDrop.

Three.js starter

A 3D scene with Three.js and orbit controls, loaded through an import map.

Open in editor Free. No install, no sign-up.
  • three

The code

Three files, exactly what you get in the editor.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Three.js starter</title>
    <script type="importmap">
      {
        "imports": {
          "three": "https://unpkg.com/three@0.170.0/build/three.module.js",
          "three/addons/": "https://unpkg.com/three@0.170.0/examples/jsm/"
        }
      }
    </script>
  </head>
  <body>
    <div id="info">
      <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - starter scene<br />
      drag to orbit, scroll to zoom
    </div>
    <a class="badge" href="https://threejs.org" target="_blank" rel="noopener"
      ><svg class="logo" viewBox="0 0 128 128" fill="currentColor" role="img" aria-label="three.js">
        <path
          d="M16.219 15.762a1.129 1.129 0 00-1.076 1.399l24.394 98.742a1.129 1.129 0 001.879.544l73.386-70.59a1.129 1.129 0 00-.47-1.899L16.55 15.806a1.129 1.129 0 00-.331-.044zm1.584 2.754l94.024 27.07-70.566 67.877-23.458-94.947z"
        />
        <path
          d="M65.137 29.84a1.129 1.129 0 00-.807.315L27.654 65.46a1.129 1.129 0 00.471 1.898L76.984 81.44a1.129 1.129 0 001.409-1.355L66.21 30.698a1.129 1.129 0 00-1.073-.858zm-.651 3.3L75.734 78.73l-45.104-13L64.486 33.14z"
        />
        <path
          d="M46.914 47.313a1.129 1.129 0 00-1.076 1.399l6.054 24.531a1.129 1.129 0 001.88.543l18.222-17.563a1.129 1.129 0 00-.472-1.898l-24.277-6.968a1.129 1.129 0 00-.331-.044zm1.583 2.751l20.522 5.89L53.614 70.8l-5.117-20.736z"
        />
        <path
          d="M40.902 22.809a1.129 1.129 0 00-.807.316L21.873 40.687a1.129 1.129 0 00.472 1.898l24.273 6.969a1.129 1.129 0 001.408-1.356l-6.051-24.53a1.129 1.129 0 00-1.073-.86zm-.65 3.3l5.114 20.736-20.517-5.89 15.403-14.847zM89.453 36.793a1.129 1.129 0 00-.806.316L70.423 54.67a1.129 1.129 0 00.472 1.899l24.274 6.968a1.129 1.129 0 001.408-1.356l-6.05-24.53a1.129 1.129 0 00-1.074-.859zm-.65 3.3l5.114 20.737L73.4 54.94l15.403-14.846zM52.944 71.864a1.129 1.129 0 00-.74.315L33.982 89.742a1.129 1.129 0 00.472 1.898l24.278 6.968a1.129 1.129 0 001.407-1.355l-6.055-24.531a1.129 1.129 0 00-1.14-.858zm-.582 3.3l5.118 20.737-20.522-5.89 15.404-14.846z"
        /></svg
    ></a>
  </body>
</html>
body {
  margin: 0;
  background-color: #000;
  color: #fff;
  font-family: Monospace;
  font-size: 13px;
  line-height: 24px;
  overscroll-behavior: none;
}
a {
  color: #ff0;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
canvas {
  display: block;
}
#info {
  position: absolute;
  top: 0;
  width: 100%;
  padding: 10px;
  box-sizing: border-box;
  text-align: center;
  user-select: none;
  pointer-events: none;
  z-index: 1;
}
#info a {
  pointer-events: auto;
}
.badge {
  position: absolute;
  left: 16px;
  bottom: 16px;
  color: #fff;
  opacity: 0.8;
}
.badge:hover {
  opacity: 1;
}
.logo {
  width: 48px;
  height: 48px;
  display: block;
}
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(70, innerWidth / innerHeight, 0.1, 100);
camera.position.set(2, 1.5, 3);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(innerWidth, innerHeight);
document.body.append(renderer.domElement);

const cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshNormalMaterial());
scene.add(cube);
scene.add(new THREE.GridHelper(10, 20, 0x444444, 0x222222));

const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

addEventListener("resize", () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});

renderer.setAnimationLoop((time) => {
  cube.rotation.x = time / 2000;
  cube.rotation.y = time / 1000;
  controls.update();
  renderer.render(scene, camera);
});

Questions

Can I use Three.js without a build step?

Yes. This starter loads Three.js straight from a CDN, so it runs in the browser with no npm install, bundler, or config.

How do I start a Three.js project online?

Click Open in editor. HTMLDrop copies this starter into a new drop with index.html, style.css, and script.js, and the preview updates as you edit.

Is it free?

Yes. Public drops, live collaboration, versions, and embeds are free, and you do not need an account to start.

Can I share or embed my Three.js demo?

Yes. Every drop gets a public link and an embed code, and you can invite others to edit it with you in real time.

More starter kits