cube.fscss is a lightweight, pure CSS 3D cube system built on FSCSS. It renders a spinnable 6-face cube using nothing but perspective, transform-style: preserve-3d, and translateZ/rotateX/rotateY โ no JavaScript, no 3D library, no canvas.
Here's example whole thing rendered live, nothing but <div>s and CSS:
<script src="https://cdn.jsdelivr.net/npm/fscss@1.1.24/exec.min.js" defer></script>
<style>
@import((*) from cube)
@cube-root()
@cube-wrapper(.my-cube)
@cube-face(.my-cube div)
@cube-face-front(.my-cube .f1)
@cube-face-back(.my-cube .f2)
@cube-face-left(.my-cube .f3)
@cube-face-right(.my-cube .f4)
@cube-face-top(.my-cube .f5)
@cube-face-bottom(.my-cube .f6)
@cube-micro-dice(.my-cube .cube)
.my-cube {
@cube-size(80px)
transform: rotateY(50deg) rotateX(30deg);
animation: spin 5s linear infinite;
}
@keyframes spin {
0% { transform: rotateX(20deg) rotateY(40deg); }
100% { transform: rotateX(380deg) rotateY(400deg); }
}
</style>
<div class="my-cube">
<div class="cube f1 dice-1"></div>
<div class="cube f2 dice-2"></div>
<div class="cube f3 dice-3"></div>
<div class="cube f4 dice-4"></div>
<div class="cube f5 dice-5"></div>
<div class="cube f6 dice-6"></div>
</div>
No dice PNGs. No SVG paths. No canvas draw calls. Every pip is a radial-gradient.
Why build this
Already had a chart/dashboard module (st-core.fscss) built on clip-path polygons โ no JS charting library, just CSS custom properties driving the shape. I wanted to see how far that "CSS does the visual math" philosophy could stretch into actual 3D space. A cube felt like the right next test: real perspective, real preserve-3d, real face geometry โ not a flat illusion.
How the geometry works
A cube is 6 absolutely-positioned faces sharing one parent set to transform-style: preserve-3d. Each face gets pushed out from the center by half the cube's edge length, then rotated to face outward:
front โ translateZ(half)
back โ rotateY(180deg) translateZ(half)
top โ rotateX(90deg) translateZ(half)
bottom โ rotateX(-90deg) translateZ(half)
right โ rotateY(90deg) translateZ(half)
left โ rotateY(-90deg) translateZ(half)
The entire cube's dimensions live in two CSS variables: --cube-size and --cube-half (always size รท 2). Resize the whole thing with one call:
.my-cube {
@cube-size(150px)
}
Faces, offsets, and dice dot size all scale together โ no manually recalculating six translateZ values by hand.
Dice pips, no font glyphs
I originally reached for Unicode dice characters (โโโโโโ
) for the pips, but font rendering for those glyphs is wildly inconsistent across platforms โ some Android/Chrome stacks show them thin, outlined, or as tofu boxes. Stacked radial-gradients solved it instead:
.dice-3 {
background-image:
radial-gradient(circle var(--cube-dot-size) at 25% 25%, var(--cube-dot-color) 99%, transparent 100%),
radial-gradient(circle var(--cube-dot-size) at 50% 50%, var(--cube-dot-color) 99%, transparent 100%),
radial-gradient(circle var(--cube-dot-size) at 75% 75%, var(--cube-dot-color) 99%, transparent 100%);
}
Font-independent, crisp at any size, and the dot radius is itself a variable โ so it scales automatically with @cube-size() instead of overflowing on a big cube or vanishing on a small one.
It's not just dice
Faces and face content are decoupled on purpose. The face mixins only handle position โ what renders inside is a separate "micro" you apply on top. Right now there are eight:
cube-micro-fire โ pulsing gradient-text fire
cube-micro-matrix โ scrolling digital rain
cube-micro-neon โ pulsing cyan/magenta glow border
cube-micro-float โ subtle bounce, stacks with anything
cube-micro-glass โ frosted backdrop-filter panel
cube-micro-holo โ holographic shifting gradient text
cube-micro-glitch โ RGB-split glitch shift
cube-micro-dice โ the pips above
Mix and match per face on the same cube:
@cube-micro-fire(.my-cube .f1)
@cube-micro-matrix(.my-cube .f2)
@cube-micro-neon(.my-cube .f3)
@cube-micro-glass(.my-cube .f5)
@cube-micro-holo(.my-cube .f6)
Try it
CDN, drop-in:
<script src="https://cdn.jsdelivr.net/npm/fscss@1.1.24/exec.min.js" defer></script>
<style>
@import((*) from cube)
/* your mixins here */
</style>
Or compile ahead of time with the CLI for a plain .css file, zero runtime:
npm install -g fscss
fscss style.fscss style.css
Full docs, token reference, and more examples: github.com/fscss-ttr/cube.fscss
If you build something with it โ I'd love to see. And if you hit issue, open an issue, it's open-source.
help us star the repo so more dev can discover it. ๐