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.
Package managers
npm install @layoutit/polycssnpm install @layoutit/polycss-reactnpm 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.
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> 