PolyCSS - CSS 3D Engine for the DOM

2 min read Original article ↗

PolyCSS

Render textured 3D meshes in the DOM with CSS. No WebGL or <canvas> needed: each polygon is a real DOM element.

Supports OBJ, glTF, GLB, and MagicaVoxel VOX files, including UV textures and material colors. Works with vanilla JS, React, and Vue.


Vanilla JS Vue React

Package managers

npm install @layoutit/polycss
npm install @layoutit/polycss-react
npm install @layoutit/polycss-vue

CDN

<script type="module" src="https://esm.sh/@layoutit/polycss/elements"></script>

How It Works

PolyCSS loads OBJ, glTF, GLB, and VOX mesh files. Each polygon becomes a DOM element positioned with transform: matrix3d(...). UV-textured triangles are packed into generated atlas sprites with CSS background positioning. The browser's compositor handles the 3D layering.

The rendered scene is a tree of standard DOM elements: no shadow DOM, no WebGL context, no canvas-as-the-whole-scene. Every polygon is individually addressable: attach click handlers, apply CSS classes, animate with CSS transitions.

View Usage Guidelines »

PolyCSS provides custom elements (<poly-camera>, <poly-scene>, <poly-mesh>), an imperative createPolyCamera / createPolyScene API, and optional React / Vue bindings. Each polygon in the mesh becomes a DOM element you can style and interact with: use whichever entry point fits your stack.

<script type="module" src="https://esm.sh/@layoutit/polycss/elements"></script>

<poly-camera rot-x="65" rot-y="45">
  <poly-scene>
    <poly-orbit-controls drag wheel animate-speed="0.3"></poly-orbit-controls>
    <poly-icosahedron size="100" color="#ff6644"></poly-icosahedron>
  </poly-scene>
</poly-camera>
import { PolyCamera, PolyScene, PolyOrbitControls, PolyIcosahedron } from "@layoutit/polycss-react";

export function App() {
  return (
    <PolyCamera rotX={65} rotY={45}>
      <PolyScene>
        <PolyOrbitControls drag wheel animate={{ speed: 0.3 }} />
        <PolyIcosahedron size={100} color="#ff6644" />
      </PolyScene>
    </PolyCamera>
  );
}
<template>
  <PolyCamera :rot-x="65" :rot-y="45">
    <PolyScene>
      <PolyOrbitControls drag wheel :animate="{ speed: 0.3 }" />
      <PolyIcosahedron :size="100" color="#ff6644" />
    </PolyScene>
  </PolyCamera>
</template>
<script setup lang="ts">
import { PolyCamera, PolyScene, PolyOrbitControls, PolyIcosahedron } from "@layoutit/polycss-vue";
</script>

Browse API Reference »