40 / 47
All 47 in 47 Tailwind CSS Toggles & Switches
- 01Tailwind iOS-Style Toggle Switch with appearance-none
- 02Tailwind Dark Mode Sun / Moon Theme Switcher
- 03Tailwind Neumorphic Soft-UI Pill Toggle
- 04Tailwind Gooey Liquid Morphing Switch with SVG Filter
- 05Tailwind Bouncy Elastic Physics Toggle (Overshoot Cubic-Bezier)
- 06Tailwind ON / OFF Text Switch with Labels Inside the Track
- 07Tailwind SaaS Pricing Toggle — Monthly / Annually Segmented Pill
- 08Tailwind Mechanical Keycap Toggles with Haptic Feedback
- 09Tailwind Waveform Mute Toggle with Animated EQ Bars
- 10Tailwind Timed Auto-Off Toggle with Conic Countdown Ring
- 11Tailwind Press-and-Hold to Confirm Toggle (Fingerprint Scan)
- 12Tailwind Split-Flap Departure Board Toggle (3D Flip)
- 13Tailwind Permission Toggle Group with :has() Live Status Badge
- 14Tailwind Material Design 3 Switch with State Layer
- 15Tailwind Skeuomorphic Wall Light Switch with Room Relight
- 16Tailwind Neon Cyberpunk Toggle with Clipped Corners
- 17Tailwind Brutalist Snap Toggle with Hard Offset Shadow
- 18Tailwind Day / Night Landscape Scene Switch
- 19Tailwind 3D Flip Card Toggle (rotateY Switch)
- 20Tailwind Sliding Pill Toggle with Label Inside the Thumb
- 21Tailwind Glassmorphism Frosted Toggle with backdrop-blur
- 22Tailwind Rotary Knob Toggle with Brushed-Metal Conic Gradient
- 23Tailwind iOS Settings List with Grouped Toggle Rows
- 24Tailwind Minimal Outline Toggle Drawn in currentColor
- 25Tailwind Squash-and-Stretch Pebble Toggle
- 26Tailwind Industrial Rocker I/O Power Switch
- 27Tailwind Accessible role=switch Toggle with forced-colors Support
- 28Tailwind Macro-Pad Toggle Grid with RGB Underglow
- 29Tailwind Radial VU Meter Mute Toggle
- 30Tailwind Segmented Pip Countdown Auto-Off Toggle
- 31Tailwind Slide-to-Confirm Toggle Rail (Drag or Arrow Keys)
- 32Tailwind Odometer Roll ON / OFF Toggle
- 33Tailwind Master Toggle with Indeterminate Tri-State
- 34Tailwind iOS Control Centre Tile Toggles
- 35Tailwind Material 3 Connected Icon Toggle Buttons
- 36Tailwind Two-Gang Wall Plate with Cumulative Room Light
- 37Tailwind Neon Toggle with Animated Conic Border Light
- 38Tailwind Brutalist Rubber-Stamp Toggle
- 39Tailwind Aurora Night Sky Toggle Switch
- 40Tailwind 3D Rotating Cube Toggle
- 41Tailwind Three-Position Off / Auto / On Selector
- 42Tailwind Liquid Glass Toggle with Specular Highlight
- 43Tailwind Three-Detent Rotary Selector Knob
- 44Tailwind Hardware Slide Switch with Knurled Grip
- 45Tailwind Battery Saver Toggle with Live Fill Meter
- 46Tailwind Morphing Sun-to-Moon Icon Toggle (SVG Stroke)
- 47Tailwind Guarded Kill Switch Under a Flip-Up Safety Cover
Tailwind 3D Rotating Cube Toggle
A solid object, not a card: two faces of a cube joined at a real edge, rotating 90° so the switch has actual thickness. v4's translate-z-* makes this the first Tailwind version where a cube needs no custom CSS at all.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="ttg-40 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg40-bg font-ttg40-sans" aria-label="3D cube toggle">
<input type="checkbox" id="ttg-40-sw" role="switch" aria-label="Deploy on push" class="peer sr-only">
<label for="ttg-40-sw" class="block cursor-pointer perspective-[600px] peer-checked:[&_.ttg40-cube]:-rotate-x-90 peer-checked:[&_.ttg40-face-a]:opacity-0 peer-checked:[&_.ttg40-face-b]:opacity-100 peer-focus-visible:outline-3 peer-focus-visible:outline-ttg40-focus peer-focus-visible:outline-offset-[6px] peer-focus-visible:rounded-2xl">
<span aria-hidden="true" class="ttg40-cube relative grid w-[190px] h-16 transform-3d transition-transform duration-[560ms] ease-[cubic-bezier(0.4,0.15,0.2,1.05)] motion-reduce:duration-150">
<span class="ttg40-face-a col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg translate-z-[32px] transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-offhi to-ttg40-offlo text-ttg40-offink shadow-[inset_0_1px_0_oklch(1_0_0/0.5)]">
<i class="not-italic w-2 h-2 rounded-full bg-ttg40-offink/50"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">MANUAL</b>
</span>
<span class="ttg40-face-b col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg rotate-x-90 translate-z-[32px] opacity-0 transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-onhi to-ttg40-onlo text-white shadow-[inset_0_1px_0_oklch(1_0_0/0.35)]">
<i class="not-italic w-2 h-2 rounded-full bg-white"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">AUTO</b>
</span>
</span>
</label>
<span class="flex flex-col items-center gap-1 text-center">
<b class="text-[15px] font-semibold text-ttg40-ink">Deploy on push</b>
<span class="text-[12.5px] text-ttg40-mute">The control is a solid object — it turns, it does not flip</span>
</span>
</section><section class="ttg-40 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg40-bg font-ttg40-sans" aria-label="3D cube toggle">
<input type="checkbox" id="ttg-40-sw" role="switch" aria-label="Deploy on push" class="peer sr-only">
<label for="ttg-40-sw" class="block cursor-pointer perspective-[600px] peer-checked:[&_.ttg40-cube]:-rotate-x-90 peer-checked:[&_.ttg40-face-a]:opacity-0 peer-checked:[&_.ttg40-face-b]:opacity-100 peer-focus-visible:outline-3 peer-focus-visible:outline-ttg40-focus peer-focus-visible:outline-offset-[6px] peer-focus-visible:rounded-2xl">
<span aria-hidden="true" class="ttg40-cube relative grid w-[190px] h-16 transform-3d transition-transform duration-[560ms] ease-[cubic-bezier(0.4,0.15,0.2,1.05)] motion-reduce:duration-150">
<span class="ttg40-face-a col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg translate-z-[32px] transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-offhi to-ttg40-offlo text-ttg40-offink shadow-[inset_0_1px_0_oklch(1_0_0/0.5)]">
<i class="not-italic w-2 h-2 rounded-full bg-ttg40-offink/50"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">MANUAL</b>
</span>
<span class="ttg40-face-b col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg rotate-x-90 translate-z-[32px] opacity-0 transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-onhi to-ttg40-onlo text-white shadow-[inset_0_1px_0_oklch(1_0_0/0.35)]">
<i class="not-italic w-2 h-2 rounded-full bg-white"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">AUTO</b>
</span>
</span>
</label>
<span class="flex flex-col items-center gap-1 text-center">
<b class="text-[15px] font-semibold text-ttg40-ink">Deploy on push</b>
<span class="text-[12.5px] text-ttg40-mute">The control is a solid object — it turns, it does not flip</span>
</span>
</section>@import "tailwindcss";
@theme {
--color-ttg40-bg: #eceef3;
--color-ttg40-bg: oklch(0.95 0.006 265);
--color-ttg40-offhi: #fbfbfd;
--color-ttg40-offhi: oklch(0.98 0.003 265);
--color-ttg40-offlo: #dcdfe8;
--color-ttg40-offlo: oklch(0.9 0.008 265);
--color-ttg40-offink: #4b5364;
--color-ttg40-offink: oklch(0.44 0.02 265);
--color-ttg40-onhi: #3d8ae8;
--color-ttg40-onhi: oklch(0.62 0.17 250);
--color-ttg40-onlo: #2a5fc4;
--color-ttg40-onlo: oklch(0.5 0.18 260);
--color-ttg40-ink: #212734;
--color-ttg40-ink: oklch(0.27 0.015 265);
--color-ttg40-mute: #7c8494;
--color-ttg40-mute: oklch(0.6 0.018 265);
--color-ttg40-focus: #3f63e0;
--color-ttg40-focus: oklch(0.55 0.19 265);
--font-ttg40-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-40 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttg40-bg: #eceef3;
--color-ttg40-bg: oklch(0.95 0.006 265);
--color-ttg40-offhi: #fbfbfd;
--color-ttg40-offhi: oklch(0.98 0.003 265);
--color-ttg40-offlo: #dcdfe8;
--color-ttg40-offlo: oklch(0.9 0.008 265);
--color-ttg40-offink: #4b5364;
--color-ttg40-offink: oklch(0.44 0.02 265);
--color-ttg40-onhi: #3d8ae8;
--color-ttg40-onhi: oklch(0.62 0.17 250);
--color-ttg40-onlo: #2a5fc4;
--color-ttg40-onlo: oklch(0.5 0.18 260);
--color-ttg40-ink: #212734;
--color-ttg40-ink: oklch(0.27 0.015 265);
--color-ttg40-mute: #7c8494;
--color-ttg40-mute: oklch(0.6 0.018 265);
--color-ttg40-focus: #3f63e0;
--color-ttg40-focus: oklch(0.55 0.19 265);
--font-ttg40-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-40 {
width: 100%;
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-ttg40-bg: #eceef3;
--color-ttg40-bg: oklch(0.95 0.006 265);
--color-ttg40-offhi: #fbfbfd;
--color-ttg40-offhi: oklch(0.98 0.003 265);
--color-ttg40-offlo: #dcdfe8;
--color-ttg40-offlo: oklch(0.9 0.008 265);
--color-ttg40-offink: #4b5364;
--color-ttg40-offink: oklch(0.44 0.02 265);
--color-ttg40-onhi: #3d8ae8;
--color-ttg40-onhi: oklch(0.62 0.17 250);
--color-ttg40-onlo: #2a5fc4;
--color-ttg40-onlo: oklch(0.5 0.18 260);
--color-ttg40-ink: #212734;
--color-ttg40-ink: oklch(0.27 0.015 265);
--color-ttg40-mute: #7c8494;
--color-ttg40-mute: oklch(0.6 0.018 265);
--color-ttg40-focus: #3f63e0;
--color-ttg40-focus: oklch(0.55 0.19 265);
--font-ttg40-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-40 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttg40-bg: #eceef3;
--color-ttg40-bg: oklch(0.95 0.006 265);
--color-ttg40-offhi: #fbfbfd;
--color-ttg40-offhi: oklch(0.98 0.003 265);
--color-ttg40-offlo: #dcdfe8;
--color-ttg40-offlo: oklch(0.9 0.008 265);
--color-ttg40-offink: #4b5364;
--color-ttg40-offink: oklch(0.44 0.02 265);
--color-ttg40-onhi: #3d8ae8;
--color-ttg40-onhi: oklch(0.62 0.17 250);
--color-ttg40-onlo: #2a5fc4;
--color-ttg40-onlo: oklch(0.5 0.18 260);
--color-ttg40-ink: #212734;
--color-ttg40-ink: oklch(0.27 0.015 265);
--color-ttg40-mute: #7c8494;
--color-ttg40-mute: oklch(0.6 0.018 265);
--color-ttg40-focus: #3f63e0;
--color-ttg40-focus: oklch(0.55 0.19 265);
--font-ttg40-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-40 {
width: 100%;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Stacking the two faces with
gridandcol-start-1 row-start-1instead ofabsolute inset-0means the cube sizes itself to its content — a small thing that makes the component reusable at any label length. translate-z-[32px]is a v4 core utility. In v3 this demo needed either a plugin or a hand-written rule for every face, which is why CSS-only cube toggles were rare in Tailwind codebases.- Both faces are opaque and no
backface-hiddenis needed, because a cube's faces never show their backs — unlike demo 19's card, where hiding the backface is the whole mechanism. - UI upgrade over demo 19: the control reads as an object with thickness rather than a card, both states name a real mode (MANUAL / AUTO) with a status dot as a second signal, and the on-gradient holds 4.9:1 for white text across both stops.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind 3D Rotating Cube Toggle
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-3d-rotating-cube-toggle/
A solid object, not a card: two faces of a cube joined at a real edge, rotating 90° so the switch has actual thickness. v4's translate-z-* makes this the first Tailwind version where a cube needs no custom CSS at all.
## HTML
```html
<section class="ttg-40 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg40-bg font-ttg40-sans" aria-label="3D cube toggle">
<input type="checkbox" id="ttg-40-sw" role="switch" aria-label="Deploy on push" class="peer sr-only">
<label for="ttg-40-sw" class="block cursor-pointer perspective-[600px] peer-checked:[&_.ttg40-cube]:-rotate-x-90 peer-checked:[&_.ttg40-face-a]:opacity-0 peer-checked:[&_.ttg40-face-b]:opacity-100 peer-focus-visible:outline-3 peer-focus-visible:outline-ttg40-focus peer-focus-visible:outline-offset-[6px] peer-focus-visible:rounded-2xl">
<span aria-hidden="true" class="ttg40-cube relative grid w-[190px] h-16 transform-3d transition-transform duration-[560ms] ease-[cubic-bezier(0.4,0.15,0.2,1.05)] motion-reduce:duration-150">
<span class="ttg40-face-a col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg translate-z-[32px] transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-offhi to-ttg40-offlo text-ttg40-offink shadow-[inset_0_1px_0_oklch(1_0_0/0.5)]">
<i class="not-italic w-2 h-2 rounded-full bg-ttg40-offink/50"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">MANUAL</b>
</span>
<span class="ttg40-face-b col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg rotate-x-90 translate-z-[32px] opacity-0 transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-onhi to-ttg40-onlo text-white shadow-[inset_0_1px_0_oklch(1_0_0/0.35)]">
<i class="not-italic w-2 h-2 rounded-full bg-white"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">AUTO</b>
</span>
</span>
</label>
<span class="flex flex-col items-center gap-1 text-center">
<b class="text-[15px] font-semibold text-ttg40-ink">Deploy on push</b>
<span class="text-[12.5px] text-ttg40-mute">The control is a solid object — it turns, it does not flip</span>
</span>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg40-bg: #eceef3;
--color-ttg40-bg: oklch(0.95 0.006 265);
--color-ttg40-offhi: #fbfbfd;
--color-ttg40-offhi: oklch(0.98 0.003 265);
--color-ttg40-offlo: #dcdfe8;
--color-ttg40-offlo: oklch(0.9 0.008 265);
--color-ttg40-offink: #4b5364;
--color-ttg40-offink: oklch(0.44 0.02 265);
--color-ttg40-onhi: #3d8ae8;
--color-ttg40-onhi: oklch(0.62 0.17 250);
--color-ttg40-onlo: #2a5fc4;
--color-ttg40-onlo: oklch(0.5 0.18 260);
--color-ttg40-ink: #212734;
--color-ttg40-ink: oklch(0.27 0.015 265);
--color-ttg40-mute: #7c8494;
--color-ttg40-mute: oklch(0.6 0.018 265);
--color-ttg40-focus: #3f63e0;
--color-ttg40-focus: oklch(0.55 0.19 265);
--font-ttg40-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-40 {
width: 100%;
min-height: 100svh;
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind 3D Rotating Cube Toggle
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-3d-rotating-cube-toggle/
A solid object, not a card: two faces of a cube joined at a real edge, rotating 90° so the switch has actual thickness. v4's translate-z-* makes this the first Tailwind version where a cube needs no custom CSS at all.
## HTML
```html
<section class="ttg-40 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg40-bg font-ttg40-sans" aria-label="3D cube toggle">
<input type="checkbox" id="ttg-40-sw" role="switch" aria-label="Deploy on push" class="peer sr-only">
<label for="ttg-40-sw" class="block cursor-pointer perspective-[600px] peer-checked:[&_.ttg40-cube]:-rotate-x-90 peer-checked:[&_.ttg40-face-a]:opacity-0 peer-checked:[&_.ttg40-face-b]:opacity-100 peer-focus-visible:outline-3 peer-focus-visible:outline-ttg40-focus peer-focus-visible:outline-offset-[6px] peer-focus-visible:rounded-2xl">
<span aria-hidden="true" class="ttg40-cube relative grid w-[190px] h-16 transform-3d transition-transform duration-[560ms] ease-[cubic-bezier(0.4,0.15,0.2,1.05)] motion-reduce:duration-150">
<span class="ttg40-face-a col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg translate-z-[32px] transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-offhi to-ttg40-offlo text-ttg40-offink shadow-[inset_0_1px_0_oklch(1_0_0/0.5)]">
<i class="not-italic w-2 h-2 rounded-full bg-ttg40-offink/50"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">MANUAL</b>
</span>
<span class="ttg40-face-b col-start-1 row-start-1 flex items-center justify-center gap-2.5 rounded-lg rotate-x-90 translate-z-[32px] opacity-0 transition-opacity duration-0 delay-[270ms] motion-reduce:delay-[70ms] bg-linear-160 from-ttg40-onhi to-ttg40-onlo text-white shadow-[inset_0_1px_0_oklch(1_0_0/0.35)]">
<i class="not-italic w-2 h-2 rounded-full bg-white"></i>
<b class="text-[15px] font-extrabold tracking-[0.16em]">AUTO</b>
</span>
</span>
</label>
<span class="flex flex-col items-center gap-1 text-center">
<b class="text-[15px] font-semibold text-ttg40-ink">Deploy on push</b>
<span class="text-[12.5px] text-ttg40-mute">The control is a solid object — it turns, it does not flip</span>
</span>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg40-bg: #eceef3;
--color-ttg40-bg: oklch(0.95 0.006 265);
--color-ttg40-offhi: #fbfbfd;
--color-ttg40-offhi: oklch(0.98 0.003 265);
--color-ttg40-offlo: #dcdfe8;
--color-ttg40-offlo: oklch(0.9 0.008 265);
--color-ttg40-offink: #4b5364;
--color-ttg40-offink: oklch(0.44 0.02 265);
--color-ttg40-onhi: #3d8ae8;
--color-ttg40-onhi: oklch(0.62 0.17 250);
--color-ttg40-onlo: #2a5fc4;
--color-ttg40-onlo: oklch(0.5 0.18 260);
--color-ttg40-ink: #212734;
--color-ttg40-ink: oklch(0.27 0.015 265);
--color-ttg40-mute: #7c8494;
--color-ttg40-mute: oklch(0.6 0.018 265);
--color-ttg40-focus: #3f63e0;
--color-ttg40-focus: oklch(0.55 0.19 265);
--font-ttg40-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-40 {
width: 100%;
min-height: 100svh;
}
```How this works
Two faces and a shared edge make a box. The front face is pushed translate-z half the depth toward the viewer; the top face is rotated 90° on X and pushed the same distance. Rotating the container by −90° swings the top face into view exactly as a real cube would turn.
Depth needs light, not just geometry. Each face carries its own gradient, and the incoming face is slightly darker at the seam — without that, two flat rectangles rotating read as a folding card.
The whole cube is the label for an sr-only checkbox, so the hit area is the full 130×64 face and the focus ring draws on the wrapper.
Make it yours
- Rotate on Y instead of X for a horizontal turn — swap both
rotate-x-*forrotate-y-*and adjust the second face. - Deeper cube: change the depth in both
translate-zvalues together; they must stay equal. - Add the remaining four faces for a die or a multi-state selector.
- Slow it to
duration-[700ms]with a spring curve for a heavier object.
Gotchas — read before shipping
- Both
translate-zvalues must be exactly half the cube's depth, or the faces do not meet and you get a visible gap at the seam. perspective-*on the wrapper,transform-3don the rotating element — swapping them flattens the rotation into a squash.- Utility ORDER does not set transform order; Tailwind composes rotate and translate through separate properties in a fixed sequence, which is why the face uses
rotate-x-90 translate-z-[32px]and not the reverse. - Under
motion-reduce:shorten the rotation rather than removing it, or the cube can end mid-turn showing an edge.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
3D transforms are universal; translate-z-*, transform-3d and perspective-* are v4 core utilities (all three needed custom CSS in v3).