4 Shape Engine: Our configurable base shape

ShapeEngine is the third step in the pack and the point where the shape gains internal structure. It builds on ShapeWithVariables by using the CSS custom properties defined there to replace the hard‑coded values in the 3d transform.

Screenshot of the ShapeEngine component, showing a centered CSS cube on a black background.
Current state of the shape, shown here as the ShapeEngine component on a black background.

The code below shows the base HTML for the shape.

<div class="scene">
        <div class="shape">
                <div class="shape__face shape__face--front">FRONT<br />ShapeEngine</div>
                <div class="shape__face shape__face--left">LEFT</div>
                <div class="shape__face shape__face--back">BACK</div>
                <div class="shape__face shape__face--right">RIGHT</div>
                <div class="shape__face shape__face--top">TOP</div>
                <div class="shape__face shape__face--bottom">BOTTOM</div>
        </div>
</div>

The code below shows the current CSS for the shape.

:root
{
        --shape-size: 200px;
        --shape-depth: 200px;
        --panel-count: 6;
        --panel-gap: 0px;

        --rotate-x: -20deg;
        --rotate-y: 25deg;
        --rotate-z: 0deg;

        --perspective: 800px;
        --perspective-origin-x: 50%;
        --perspective-origin-y: 50%;

        --face-front-rotate: 0deg;
        --face-left-rotate: -90deg;
        --face-back-rotate: 180deg;
        --face-right-rotate: 90deg;
        --face-top-rotate: 90deg;
        --face-bottom-rotate: -90deg;
}

body
{
        margin: 0;
        min-height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        background: #05060a;
        color: #f5f5f5;
        font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif;
}

.scene
{
        width: 200px;
        height: 200px;
        perspective: 800px;
        perspective-origin: 50% 50%;
}

.shape
{
        position: relative;
        width: 100%;
        height: 100%;
        transform-style: preserve-3d;
        transform: rotateX(-20deg) rotateY(25deg) rotateZ(0deg);
}

.shape__face
{
        position: absolute;
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        background: linear-gradient(135deg, #1b1f2a, #2c3244);
        outline: 1px solid rgba(255, 255, 255, 0.15);
        box-sizing: border-box;
}

.shape__face--front { transform: rotateY(var(--face-front-rotate)) translateZ(calc(var(--shape-depth) / 2)); }
.shape__face--left { transform: rotateY(var(--face-left-rotate)) translateZ(calc(var(--shape-depth) / 2)); }
.shape__face--back { transform: rotateY(var(--face-back-rotate)) translateZ(calc(var(--shape-depth) / 2)); }
.shape__face--right { transform: rotateY(var(--face-right-rotate)) translateZ(calc(var(--shape-depth) / 2)); }
.shape__face--top { transform: rotateX(var(--face-top-rotate)) translateZ(calc(var(--shape-depth) / 2)); }
.shape__face--bottom { transform: rotateX(var(--face-bottom-rotate)) translateZ(calc(var(--shape-depth) / 2)); }

The goal of this step is to complete the foundation of an extensible CSS shape.

The folder includes:

  • an updated HTML file with the simple shape
  • a CSS file that replaces the hard‑coded values in the transforms with CSS custom properties
  • a short note describing what changed from ShapeWithVariables

What changed from the previous step.

  • Change: Completed the move from fixed transform values to fully variable‑driven transforms.
  • Reason: Make the shape fully adjustable through custom properties while keeping the component simple and readable.

This step completes the core of the shape engine. With all transform values now driven by custom properties, the component becomes flexible without adding complexity, and the progression reaches its intended foundation.

More Artwork