The finishing craft. Fake directional light so a cube looks solid, then explore the unglamorous essentials: will-change, z-fighting, and prefers-reduced-motion.
CSS has no real lights. We fake one: each face gets a semi-transparent black overlay, darker the more it faces away from an imaginary light at the top-front. Toggle shading off — the cube turns into a flat, confusing blob of one color.
3D transform animations run on the GPU compositor — buttery and cheap. will-change: transform promotes the element to its own layer before it animates, avoiding a first-frame hitch. But it costs memory, so use it sparingly and ideally remove it when idle.
Current: will-change: auto — open DevTools › Layers to see the element get its own composited layer when enabled.
Golden rule: animate only transform and opacity for 3D. Animating top/left/width forces layout every frame and janks on phones.
When two surfaces sit at the exact same depth, the GPU can't decide which is in front, so they flicker and tear as the view moves. The fix: nudge one apart with translateZ(1px).
Two coplanar panels above. Toggle the fix and the speckled tearing disappears.
Spinning, parallax, and big 3D moves can trigger nausea and vestibular issues. Always honor @media (prefers-reduced-motion: reduce) — stop the spin, or replace it with a gentle cross-fade. Simulate it here:
Your OS currently reports: checking…
In real CSS you'd write @media (prefers-reduced-motion: reduce) { .obj { animation: none } } — no JS required. This button just simulates the effect in-page.