Loaders✨ Premium

Cube Flip

A 40 px square with an indigo → purple gradient, two chained 180° flips (X axis then Y axis) over 1.2 s, inline 120 px perspective — one div, zero JS.

CSS3D

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Loaders has 29 effects, including 4 free. Explore the category →

3 usage examples

Submit button — “processing” state — Cube Flip example 1

① Submit button — “processing” state

WhenA "Send" or "Confirm" button replaces its label with the cube while the HTTP request is in flight.
WhyThe 40 px element fits inside a standard button. Its mechanical tumble — no tail, no embellishment — communicates "working" without distracting from the rest of the interface. One div replaces the label.
Settingswidth: 28px; height: 28px to fit inside a 40 px button; linear-gradient(135deg, #fff, #ddd) on a dark button background, or keep #6366f1 → #8b5cf6 on a light one.
CI build console — the package assembling beside the log — Cube Flip example 2

② CI build console — the package assembling beside the log

WhenA developer console (CI pipeline, bundler, publish to a package registry) shows the cube at full size while the build log scrolls: as long as the package is not bundled, it keeps tumbling.
WhyThe square is the package glyph — npm, Docker and every registry draw a box. Watching it tumble on two axes is watching the package being turned over while it is assembled: the meaning reads without a label. Its two mechanical half-turns, one axis then the other, match the discrete build steps (transform, then bundle) that the log ticks off beside it. A ring or three dots would only say “working”; here the shape says what is working. And the flat element with a 3:1 perspective stays crisp at 72 px, where an enlarged spinner would be nothing but a big empty circle.
Settingswidth: 72px; height: 72px so the tumble reads next to the log; perspective(216px) copied into all three keyframes (3:1 ratio preserved, see Customize); duration 1.2s and gradient #6366f1 → #8b5cf6 left at their defaults — on the console's dark background the contrast holds at 4.7:1.
AI content generation — indicator inside a response area — Cube Flip example 3

③ AI content generation — indicator inside a response area

WhenA text response field or a generated-image area shows the cube while the model is computing.
WhyFlipping on two axes suggests transformation in progress — input becoming output. The motion is more expressive than a spinning ring in a technical product. The lack of JavaScript is no obstacle: showing and hiding the cube is handled by the application's own logic.
Settingsanimation-duration: 0.9s for a slightly snappier pace, perspective reduced to 80px for a more pronounced 3D effect, color adapted to the interface theme.

How it works

The effect is a single element: .loader-cube, a 40 × 40 px square, linear-gradient(135deg, #6366f1, #8b5cf6) background (indigo → purple). No children, no JavaScript, no CSS variables.

The cubeFlip animation (1.2 s, ease-in-out, infinite) splits the cycle into two equal 0.6 s phases. Phase 1 (0% → 50%): rotateX goes from 0° to −180° — the square tips forward, its top edge coming toward the viewer. Phase 2 (50% → 100%): rotateX stays at −180°, rotateY goes from 0° to −180° — the already-flipped element pivots on its vertical axis. The value perspective(120px) is written into the transform property of each keyframe rather than on a parent: every instance has its own independent vanishing point. On a 40 px element, the perspective-to-size ratio is 3:1 — noticeable but not exaggerated.

Since no backface-visibility: hidden or transform-style: preserve-3d is declared, the element's back face is visible at 180° — it is the same gradient, flipped horizontally (the indigo corner moves from top-left to top-right). Measured in Chromium: near the axis (~77° of rotation around X), the rendered height of the 40 px element drops to 9 px and the width rises to 48 px from the near-edge enlargement effect of the perspective.

Accessibility

  • prefers-reduced-motion not handled: the cubeFlip animation runs continuously regardless of system preferences — measured: animationPlayState: running under prefers-reduced-motion: reduce. Add: @media (prefers-reduced-motion: reduce) { .loader-cube { animation: none; } }.
  • The cube is purely visual: no role, no text, no aria-live region. As a loading indicator it must be paired with a visually hidden element carrying role="status" or aria-live="polite" (e.g. <span class="sr-only" role="status">Loading…</span>). Set aria-hidden="true" on .loader-cube so screen readers do not traverse the decorative element.
  • Contrast: the indigo gradient (#6366f1) on white yields only 2.6:1, below the 3:1 threshold for non-text UI components; on the code's dark background (#0a0a0f) it reaches 4.7:1. On a light page, darken the hues (e.g. #4338ca → #7c3aed).
  • The 40 × 40 px element is not interactive. If placed inside a button, the <button> carries the focus and the ARIA label — the cube receives aria-hidden="true".

Browser compatibility

Requires @keyframes, animation, transform: perspective() rotateX() rotateY() and linear-gradient. No library, no CSS variables, no JavaScript.

Chrome 36+✓ Full
Firefox 16+✓ Full
Safari 9+✓ Full
Edge 12+✓ Full
Mobile iOS 9+✓ Full
Android Chrome✓ Full

Without rotateX/rotateY, the square remains static in indigo. Without @keyframes, same result — a visible static square.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="loader-cube"></div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Size (CSS — .loader-cube) 40 × 40 px Height and width in px or em. The perspective is in absolute pixels (120px): if you scale the element up significantly, increase the perspective proportionally to keep the same foreshortening ratio.
Background color (CSS — background) linear-gradient(135deg, #6366f1, #8b5cf6) Gradient or solid color. The back face shows the same gradient flipped horizontally; a solid color removes this mirror effect.
Duration (CSS — animation: 1.2s …) 1.2 s Time for one full cycle (two flips). 0.8s = hurried pace; 2s = slow, deliberate rotation.
Easing (CSS — ease-in-out) ease-in-out Acceleration curve applied to both phases independently. linear gives constant rotation speed; ease-in-out produces an acceleration at the center of each half-turn and a brief rest at each full-face position.
Perspective (CSS — perspective(120px) in each keyframe) 120 px (3:1 ratio relative to the 40 px element) Simulated viewing distance. 80px (2:1) = strong 3D effect; 200px (5:1) = near-isometric rotation, little foreshortening. Change the value in all three keyframes (0%, 50%, 100%) at once.
Back face visibility (add — backface-visibility: hidden) back face visible (CSS default) Without this rule, the reversed gradient is visible at 180°. With backface-visibility: hidden, the element disappears at the axis crossing, creating a clean blank phase between the two face orientations.
Reduced motion (add) not in the sold code @media (prefers-reduced-motion: reduce) { .loader-cube { animation: none; } } freezes the cube. Alternatively, increase the duration to 4s for very slow motion rather than stopping it entirely.

FAQ

The word describes the shape (a square, one face of a cube), not a geometric construction. There is no transform-style: preserve-3d and no child faces. The 3D illusion comes from perspective(120px) rotateX() rotateY() applied to a flat element: as it tips, the perspective distorts its projection, compressing it down to 9 px tall at the axis crossing. The back face is the same gradient reversed — not a distinct face.
Cube Grid is nine independent squares that pulse in 2D (scale 1 → 0 → 1) with staggered delays — an agitated grid animation. Cube Flip is a single element performing a real 3D rotation in two distinct phases on two axes. The techniques have nothing in common: Cube Grid uses no perspective or rotateX/rotateY, and Cube Flip has no grid or timing offset. Note: the CSS sold with Cube Flip mistakenly includes the full Cube Grid code (@keyframes cubeGridScale and the 11 .loader-cube-grid rules) — it can be deleted without affecting Cube Flip.
The CSS perspective property on a parent creates a shared 3D space for all children — one vanishing point, centered on the parent. The perspective() transform function creates a 3D space local to each element, centered on itself. Consequence here: two .loader-cube instances side by side each have their own vanishing point and animate independently, without one element's perspective distorting the other.