26 / 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 Industrial Rocker I/O Power Switch
The power switch off the back of real hardware: a rectangular rocker with engraved I and O halves seesawing inside a riveted steel panel, and a red pilot lamp that ignites on power. Perspective, gradients and text-shadow do all the machining.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="ttg-26 w-full min-h-svh flex flex-col items-center justify-center gap-7 px-5 py-14 bg-ttg26-bg font-ttg26-sans" aria-label="Industrial rocker power switch">
<div class="relative flex flex-col items-center gap-3 px-11 pt-9 pb-5 rounded-[10px] [background:repeating-linear-gradient(92deg,var(--color-ttg26-steelhi)_0_2px,var(--color-ttg26-steello)_2px_4px)] shadow-[0_22px_46px_-20px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.18),inset_0_-2px_4px_oklch(0_0_0/0.4)] has-checked:[&_.ttg26-lamp]:bg-ttg26-lamp has-checked:[&_.ttg26-lamp]:shadow-[0_0_8px_var(--color-ttg26-lamp),0_0_20px_color-mix(in_oklab,var(--color-ttg26-lamp)_50%,transparent)]">
<span aria-hidden="true" class="absolute top-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute top-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="ttg26-lamp absolute top-3.5 right-5.5 w-3 h-3 rounded-full bg-ttg26-lampdark shadow-[inset_0_1px_3px_oklch(0_0_0/0.8)] transition-[background-color,box-shadow] duration-200"></span>
<span class="relative block w-15 h-28 p-[5px] rounded-[7px] bg-ttg26-well shadow-[inset_0_3px_8px_oklch(0_0_0/0.85),inset_0_0_0_2px_var(--color-ttg26-wellring)] perspective-[280px]">
<input type="checkbox" id="ttg-26-sw" role="switch" aria-label="Main power" class="peer sr-only">
<label for="ttg-26-sw" aria-hidden="true" class="grid grid-rows-2 w-full h-full rounded-[5px] cursor-pointer bg-linear-to-b from-ttg26-rockerlo via-ttg26-rockerhi via-50% to-ttg26-rockerdk origin-center rotate-x-[-16deg] transition-transform duration-[160ms] ease-[cubic-bezier(0.5,1.5,0.6,1)] peer-checked:rotate-x-[16deg] peer-checked:bg-linear-to-t peer-checked:[&_.ttg26-i]:text-ttg26-lit peer-checked:[&_.ttg26-o]:text-ttg26-dim peer-focus-visible:outline-3 peer-focus-visible:outline-ttg26-focus peer-focus-visible:outline-offset-[5px] motion-reduce:transition-none">
<i class="ttg26-i grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-dim [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">I</i>
<i class="ttg26-o grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-lit [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">O</i>
</label>
</span>
<span class="px-2.5 py-[3px] rounded-[3px] bg-ttg26-tag text-ttg26-tagink text-[10px] font-bold tracking-[0.24em] shadow-[inset_0_1px_0_oklch(1_0_0/0.6)]">MAIN PWR</span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg26-mute">IEC rocker · I = on, O = off</p>
</section><section class="ttg-26 w-full min-h-svh flex flex-col items-center justify-center gap-7 px-5 py-14 bg-ttg26-bg font-ttg26-sans" aria-label="Industrial rocker power switch">
<div class="relative flex flex-col items-center gap-3 px-11 pt-9 pb-5 rounded-[10px] [background:repeating-linear-gradient(92deg,var(--color-ttg26-steelhi)_0_2px,var(--color-ttg26-steello)_2px_4px)] shadow-[0_22px_46px_-20px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.18),inset_0_-2px_4px_oklch(0_0_0/0.4)] has-checked:[&_.ttg26-lamp]:bg-ttg26-lamp has-checked:[&_.ttg26-lamp]:shadow-[0_0_8px_var(--color-ttg26-lamp),0_0_20px_color-mix(in_oklab,var(--color-ttg26-lamp)_50%,transparent)]">
<span aria-hidden="true" class="absolute top-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute top-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="ttg26-lamp absolute top-3.5 right-5.5 w-3 h-3 rounded-full bg-ttg26-lampdark shadow-[inset_0_1px_3px_oklch(0_0_0/0.8)] transition-[background-color,box-shadow] duration-200"></span>
<span class="relative block w-15 h-28 p-[5px] rounded-[7px] bg-ttg26-well shadow-[inset_0_3px_8px_oklch(0_0_0/0.85),inset_0_0_0_2px_var(--color-ttg26-wellring)] perspective-[280px]">
<input type="checkbox" id="ttg-26-sw" role="switch" aria-label="Main power" class="peer sr-only">
<label for="ttg-26-sw" aria-hidden="true" class="grid grid-rows-2 w-full h-full rounded-[5px] cursor-pointer bg-linear-to-b from-ttg26-rockerlo via-ttg26-rockerhi via-50% to-ttg26-rockerdk origin-center rotate-x-[-16deg] transition-transform duration-[160ms] ease-[cubic-bezier(0.5,1.5,0.6,1)] peer-checked:rotate-x-[16deg] peer-checked:bg-linear-to-t peer-checked:[&_.ttg26-i]:text-ttg26-lit peer-checked:[&_.ttg26-o]:text-ttg26-dim peer-focus-visible:outline-3 peer-focus-visible:outline-ttg26-focus peer-focus-visible:outline-offset-[5px] motion-reduce:transition-none">
<i class="ttg26-i grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-dim [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">I</i>
<i class="ttg26-o grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-lit [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">O</i>
</label>
</span>
<span class="px-2.5 py-[3px] rounded-[3px] bg-ttg26-tag text-ttg26-tagink text-[10px] font-bold tracking-[0.24em] shadow-[inset_0_1px_0_oklch(1_0_0/0.6)]">MAIN PWR</span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg26-mute">IEC rocker · I = on, O = off</p>
</section>@import "tailwindcss";
@theme {
--color-ttg26-bg: #1d1f24;
--color-ttg26-bg: oklch(0.24 0.006 265);
--color-ttg26-steelhi: #5a5f68;
--color-ttg26-steelhi: oklch(0.47 0.008 265);
--color-ttg26-steello: #4f545d;
--color-ttg26-steello: oklch(0.43 0.008 265);
--color-ttg26-rivethi: #a2a8b3;
--color-ttg26-rivethi: oklch(0.72 0.01 265);
--color-ttg26-rivetlo: #4a4f58;
--color-ttg26-rivetlo: oklch(0.42 0.009 265);
--color-ttg26-well: #191b1f;
--color-ttg26-well: oklch(0.21 0.006 265);
--color-ttg26-wellring: #101114;
--color-ttg26-wellring: oklch(0.16 0.005 265);
--color-ttg26-rockerhi: #3c4049;
--color-ttg26-rockerhi: oklch(0.36 0.008 265);
--color-ttg26-rockerlo: #2c2f35;
--color-ttg26-rockerlo: oklch(0.29 0.007 265);
--color-ttg26-rockerdk: #22252a;
--color-ttg26-rockerdk: oklch(0.25 0.006 265);
--color-ttg26-dim: #8b919d;
--color-ttg26-dim: oklch(0.65 0.012 265);
--color-ttg26-lit: #dde2ea;
--color-ttg26-lit: oklch(0.91 0.008 265);
--color-ttg26-lamp: #ff4a3d;
--color-ttg26-lamp: oklch(0.65 0.22 27);
--color-ttg26-lampdark: #3d2426;
--color-ttg26-lampdark: oklch(0.29 0.03 20);
--color-ttg26-tag: #c2c7d0;
--color-ttg26-tag: oklch(0.83 0.008 265);
--color-ttg26-tagink: #1e2128;
--color-ttg26-tagink: oklch(0.24 0.008 265);
--color-ttg26-mute: #7c828c;
--color-ttg26-mute: oklch(0.6 0.01 265);
--color-ttg26-focus: #6cb6f0;
--color-ttg26-focus: oklch(0.74 0.14 235);
--font-ttg26-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-26 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttg26-bg: #1d1f24;
--color-ttg26-bg: oklch(0.24 0.006 265);
--color-ttg26-steelhi: #5a5f68;
--color-ttg26-steelhi: oklch(0.47 0.008 265);
--color-ttg26-steello: #4f545d;
--color-ttg26-steello: oklch(0.43 0.008 265);
--color-ttg26-rivethi: #a2a8b3;
--color-ttg26-rivethi: oklch(0.72 0.01 265);
--color-ttg26-rivetlo: #4a4f58;
--color-ttg26-rivetlo: oklch(0.42 0.009 265);
--color-ttg26-well: #191b1f;
--color-ttg26-well: oklch(0.21 0.006 265);
--color-ttg26-wellring: #101114;
--color-ttg26-wellring: oklch(0.16 0.005 265);
--color-ttg26-rockerhi: #3c4049;
--color-ttg26-rockerhi: oklch(0.36 0.008 265);
--color-ttg26-rockerlo: #2c2f35;
--color-ttg26-rockerlo: oklch(0.29 0.007 265);
--color-ttg26-rockerdk: #22252a;
--color-ttg26-rockerdk: oklch(0.25 0.006 265);
--color-ttg26-dim: #8b919d;
--color-ttg26-dim: oklch(0.65 0.012 265);
--color-ttg26-lit: #dde2ea;
--color-ttg26-lit: oklch(0.91 0.008 265);
--color-ttg26-lamp: #ff4a3d;
--color-ttg26-lamp: oklch(0.65 0.22 27);
--color-ttg26-lampdark: #3d2426;
--color-ttg26-lampdark: oklch(0.29 0.03 20);
--color-ttg26-tag: #c2c7d0;
--color-ttg26-tag: oklch(0.83 0.008 265);
--color-ttg26-tagink: #1e2128;
--color-ttg26-tagink: oklch(0.24 0.008 265);
--color-ttg26-mute: #7c828c;
--color-ttg26-mute: oklch(0.6 0.01 265);
--color-ttg26-focus: #6cb6f0;
--color-ttg26-focus: oklch(0.74 0.14 235);
--font-ttg26-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-26 {
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-ttg26-bg: #1d1f24;
--color-ttg26-bg: oklch(0.24 0.006 265);
--color-ttg26-steelhi: #5a5f68;
--color-ttg26-steelhi: oklch(0.47 0.008 265);
--color-ttg26-steello: #4f545d;
--color-ttg26-steello: oklch(0.43 0.008 265);
--color-ttg26-rivethi: #a2a8b3;
--color-ttg26-rivethi: oklch(0.72 0.01 265);
--color-ttg26-rivetlo: #4a4f58;
--color-ttg26-rivetlo: oklch(0.42 0.009 265);
--color-ttg26-well: #191b1f;
--color-ttg26-well: oklch(0.21 0.006 265);
--color-ttg26-wellring: #101114;
--color-ttg26-wellring: oklch(0.16 0.005 265);
--color-ttg26-rockerhi: #3c4049;
--color-ttg26-rockerhi: oklch(0.36 0.008 265);
--color-ttg26-rockerlo: #2c2f35;
--color-ttg26-rockerlo: oklch(0.29 0.007 265);
--color-ttg26-rockerdk: #22252a;
--color-ttg26-rockerdk: oklch(0.25 0.006 265);
--color-ttg26-dim: #8b919d;
--color-ttg26-dim: oklch(0.65 0.012 265);
--color-ttg26-lit: #dde2ea;
--color-ttg26-lit: oklch(0.91 0.008 265);
--color-ttg26-lamp: #ff4a3d;
--color-ttg26-lamp: oklch(0.65 0.22 27);
--color-ttg26-lampdark: #3d2426;
--color-ttg26-lampdark: oklch(0.29 0.03 20);
--color-ttg26-tag: #c2c7d0;
--color-ttg26-tag: oklch(0.83 0.008 265);
--color-ttg26-tagink: #1e2128;
--color-ttg26-tagink: oklch(0.24 0.008 265);
--color-ttg26-mute: #7c828c;
--color-ttg26-mute: oklch(0.6 0.01 265);
--color-ttg26-focus: #6cb6f0;
--color-ttg26-focus: oklch(0.74 0.14 235);
--font-ttg26-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-26 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttg26-bg: #1d1f24;
--color-ttg26-bg: oklch(0.24 0.006 265);
--color-ttg26-steelhi: #5a5f68;
--color-ttg26-steelhi: oklch(0.47 0.008 265);
--color-ttg26-steello: #4f545d;
--color-ttg26-steello: oklch(0.43 0.008 265);
--color-ttg26-rivethi: #a2a8b3;
--color-ttg26-rivethi: oklch(0.72 0.01 265);
--color-ttg26-rivetlo: #4a4f58;
--color-ttg26-rivetlo: oklch(0.42 0.009 265);
--color-ttg26-well: #191b1f;
--color-ttg26-well: oklch(0.21 0.006 265);
--color-ttg26-wellring: #101114;
--color-ttg26-wellring: oklch(0.16 0.005 265);
--color-ttg26-rockerhi: #3c4049;
--color-ttg26-rockerhi: oklch(0.36 0.008 265);
--color-ttg26-rockerlo: #2c2f35;
--color-ttg26-rockerlo: oklch(0.29 0.007 265);
--color-ttg26-rockerdk: #22252a;
--color-ttg26-rockerdk: oklch(0.25 0.006 265);
--color-ttg26-dim: #8b919d;
--color-ttg26-dim: oklch(0.65 0.012 265);
--color-ttg26-lit: #dde2ea;
--color-ttg26-lit: oklch(0.91 0.008 265);
--color-ttg26-lamp: #ff4a3d;
--color-ttg26-lamp: oklch(0.65 0.22 27);
--color-ttg26-lampdark: #3d2426;
--color-ttg26-lampdark: oklch(0.29 0.03 20);
--color-ttg26-tag: #c2c7d0;
--color-ttg26-tag: oklch(0.83 0.008 265);
--color-ttg26-tagink: #1e2128;
--color-ttg26-tagink: oklch(0.24 0.008 265);
--color-ttg26-mute: #7c828c;
--color-ttg26-mute: oklch(0.6 0.01 265);
--color-ttg26-focus: #6cb6f0;
--color-ttg26-focus: oklch(0.74 0.14 235);
--font-ttg26-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-26 {
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.
- The gradient flip is
peer-checked:bg-linear-to-t— one utility instead of the original's full restated gradient, and the same move as the wall switch in demo 15. Direction is the only thing that should change when a surface tips. - Both legend swaps live on the label as
peer-checked:[&_.ttg26-i]:/peer-checked:[&_.ttg26-o]:. The obvious shortcut —peer-checked:text-*on the legend itself — silently never matches, because the legends are descendants of the label, not siblings of thepeerinput;peer-*only ever reaches later SIBLINGS. - Brushed steel is
[background:repeating-linear-gradient(...)]reading two metal tokens, so the panel finish is themeable even though the grain itself is an arbitrary value. - UI change from the CSS original: the unlit legend rose from
#878d99tooklch(0.65)(and the two legend tokens were renamed-dim/-lit, becausetext-ttg26-legendandtext-ttg26-legendlitare a prefix pair and one shadowed the other) and the caption from#5a5f68tooklch(0.6)— 4.5:1 and 4.8:1 against their surfaces, where both previously sat near 2.8:1 and the OFF half of an IEC switch was effectively unlabelled.
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 Industrial Rocker I/O Power Switch
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-industrial-rocker-io-power-switch/
The power switch off the back of real hardware: a rectangular rocker with engraved I and O halves seesawing inside a riveted steel panel, and a red pilot lamp that ignites on power. Perspective, gradients and text-shadow do all the machining.
## HTML
```html
<section class="ttg-26 w-full min-h-svh flex flex-col items-center justify-center gap-7 px-5 py-14 bg-ttg26-bg font-ttg26-sans" aria-label="Industrial rocker power switch">
<div class="relative flex flex-col items-center gap-3 px-11 pt-9 pb-5 rounded-[10px] [background:repeating-linear-gradient(92deg,var(--color-ttg26-steelhi)_0_2px,var(--color-ttg26-steello)_2px_4px)] shadow-[0_22px_46px_-20px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.18),inset_0_-2px_4px_oklch(0_0_0/0.4)] has-checked:[&_.ttg26-lamp]:bg-ttg26-lamp has-checked:[&_.ttg26-lamp]:shadow-[0_0_8px_var(--color-ttg26-lamp),0_0_20px_color-mix(in_oklab,var(--color-ttg26-lamp)_50%,transparent)]">
<span aria-hidden="true" class="absolute top-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute top-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="ttg26-lamp absolute top-3.5 right-5.5 w-3 h-3 rounded-full bg-ttg26-lampdark shadow-[inset_0_1px_3px_oklch(0_0_0/0.8)] transition-[background-color,box-shadow] duration-200"></span>
<span class="relative block w-15 h-28 p-[5px] rounded-[7px] bg-ttg26-well shadow-[inset_0_3px_8px_oklch(0_0_0/0.85),inset_0_0_0_2px_var(--color-ttg26-wellring)] perspective-[280px]">
<input type="checkbox" id="ttg-26-sw" role="switch" aria-label="Main power" class="peer sr-only">
<label for="ttg-26-sw" aria-hidden="true" class="grid grid-rows-2 w-full h-full rounded-[5px] cursor-pointer bg-linear-to-b from-ttg26-rockerlo via-ttg26-rockerhi via-50% to-ttg26-rockerdk origin-center rotate-x-[-16deg] transition-transform duration-[160ms] ease-[cubic-bezier(0.5,1.5,0.6,1)] peer-checked:rotate-x-[16deg] peer-checked:bg-linear-to-t peer-checked:[&_.ttg26-i]:text-ttg26-lit peer-checked:[&_.ttg26-o]:text-ttg26-dim peer-focus-visible:outline-3 peer-focus-visible:outline-ttg26-focus peer-focus-visible:outline-offset-[5px] motion-reduce:transition-none">
<i class="ttg26-i grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-dim [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">I</i>
<i class="ttg26-o grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-lit [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">O</i>
</label>
</span>
<span class="px-2.5 py-[3px] rounded-[3px] bg-ttg26-tag text-ttg26-tagink text-[10px] font-bold tracking-[0.24em] shadow-[inset_0_1px_0_oklch(1_0_0/0.6)]">MAIN PWR</span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg26-mute">IEC rocker · I = on, O = off</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg26-bg: #1d1f24;
--color-ttg26-bg: oklch(0.24 0.006 265);
--color-ttg26-steelhi: #5a5f68;
--color-ttg26-steelhi: oklch(0.47 0.008 265);
--color-ttg26-steello: #4f545d;
--color-ttg26-steello: oklch(0.43 0.008 265);
--color-ttg26-rivethi: #a2a8b3;
--color-ttg26-rivethi: oklch(0.72 0.01 265);
--color-ttg26-rivetlo: #4a4f58;
--color-ttg26-rivetlo: oklch(0.42 0.009 265);
--color-ttg26-well: #191b1f;
--color-ttg26-well: oklch(0.21 0.006 265);
--color-ttg26-wellring: #101114;
--color-ttg26-wellring: oklch(0.16 0.005 265);
--color-ttg26-rockerhi: #3c4049;
--color-ttg26-rockerhi: oklch(0.36 0.008 265);
--color-ttg26-rockerlo: #2c2f35;
--color-ttg26-rockerlo: oklch(0.29 0.007 265);
--color-ttg26-rockerdk: #22252a;
--color-ttg26-rockerdk: oklch(0.25 0.006 265);
--color-ttg26-dim: #8b919d;
--color-ttg26-dim: oklch(0.65 0.012 265);
--color-ttg26-lit: #dde2ea;
--color-ttg26-lit: oklch(0.91 0.008 265);
--color-ttg26-lamp: #ff4a3d;
--color-ttg26-lamp: oklch(0.65 0.22 27);
--color-ttg26-lampdark: #3d2426;
--color-ttg26-lampdark: oklch(0.29 0.03 20);
--color-ttg26-tag: #c2c7d0;
--color-ttg26-tag: oklch(0.83 0.008 265);
--color-ttg26-tagink: #1e2128;
--color-ttg26-tagink: oklch(0.24 0.008 265);
--color-ttg26-mute: #7c828c;
--color-ttg26-mute: oklch(0.6 0.01 265);
--color-ttg26-focus: #6cb6f0;
--color-ttg26-focus: oklch(0.74 0.14 235);
--font-ttg26-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-26 {
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 Industrial Rocker I/O Power Switch
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-industrial-rocker-io-power-switch/
The power switch off the back of real hardware: a rectangular rocker with engraved I and O halves seesawing inside a riveted steel panel, and a red pilot lamp that ignites on power. Perspective, gradients and text-shadow do all the machining.
## HTML
```html
<section class="ttg-26 w-full min-h-svh flex flex-col items-center justify-center gap-7 px-5 py-14 bg-ttg26-bg font-ttg26-sans" aria-label="Industrial rocker power switch">
<div class="relative flex flex-col items-center gap-3 px-11 pt-9 pb-5 rounded-[10px] [background:repeating-linear-gradient(92deg,var(--color-ttg26-steelhi)_0_2px,var(--color-ttg26-steello)_2px_4px)] shadow-[0_22px_46px_-20px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.18),inset_0_-2px_4px_oklch(0_0_0/0.4)] has-checked:[&_.ttg26-lamp]:bg-ttg26-lamp has-checked:[&_.ttg26-lamp]:shadow-[0_0_8px_var(--color-ttg26-lamp),0_0_20px_color-mix(in_oklab,var(--color-ttg26-lamp)_50%,transparent)]">
<span aria-hidden="true" class="absolute top-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute top-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 left-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="absolute bottom-2 right-2 w-[9px] h-[9px] rounded-full bg-radial-[at_35%_30%] from-ttg26-rivethi to-ttg26-rivetlo shadow-[inset_0_-1px_2px_oklch(0_0_0/0.6)]"></span>
<span aria-hidden="true" class="ttg26-lamp absolute top-3.5 right-5.5 w-3 h-3 rounded-full bg-ttg26-lampdark shadow-[inset_0_1px_3px_oklch(0_0_0/0.8)] transition-[background-color,box-shadow] duration-200"></span>
<span class="relative block w-15 h-28 p-[5px] rounded-[7px] bg-ttg26-well shadow-[inset_0_3px_8px_oklch(0_0_0/0.85),inset_0_0_0_2px_var(--color-ttg26-wellring)] perspective-[280px]">
<input type="checkbox" id="ttg-26-sw" role="switch" aria-label="Main power" class="peer sr-only">
<label for="ttg-26-sw" aria-hidden="true" class="grid grid-rows-2 w-full h-full rounded-[5px] cursor-pointer bg-linear-to-b from-ttg26-rockerlo via-ttg26-rockerhi via-50% to-ttg26-rockerdk origin-center rotate-x-[-16deg] transition-transform duration-[160ms] ease-[cubic-bezier(0.5,1.5,0.6,1)] peer-checked:rotate-x-[16deg] peer-checked:bg-linear-to-t peer-checked:[&_.ttg26-i]:text-ttg26-lit peer-checked:[&_.ttg26-o]:text-ttg26-dim peer-focus-visible:outline-3 peer-focus-visible:outline-ttg26-focus peer-focus-visible:outline-offset-[5px] motion-reduce:transition-none">
<i class="ttg26-i grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-dim [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">I</i>
<i class="ttg26-o grid place-items-center not-italic text-[17px] font-extrabold text-ttg26-lit [text-shadow:0_-1px_1px_oklch(0_0_0/0.8),0_1px_1px_oklch(1_0_0/0.15)]">O</i>
</label>
</span>
<span class="px-2.5 py-[3px] rounded-[3px] bg-ttg26-tag text-ttg26-tagink text-[10px] font-bold tracking-[0.24em] shadow-[inset_0_1px_0_oklch(1_0_0/0.6)]">MAIN PWR</span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg26-mute">IEC rocker · I = on, O = off</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg26-bg: #1d1f24;
--color-ttg26-bg: oklch(0.24 0.006 265);
--color-ttg26-steelhi: #5a5f68;
--color-ttg26-steelhi: oklch(0.47 0.008 265);
--color-ttg26-steello: #4f545d;
--color-ttg26-steello: oklch(0.43 0.008 265);
--color-ttg26-rivethi: #a2a8b3;
--color-ttg26-rivethi: oklch(0.72 0.01 265);
--color-ttg26-rivetlo: #4a4f58;
--color-ttg26-rivetlo: oklch(0.42 0.009 265);
--color-ttg26-well: #191b1f;
--color-ttg26-well: oklch(0.21 0.006 265);
--color-ttg26-wellring: #101114;
--color-ttg26-wellring: oklch(0.16 0.005 265);
--color-ttg26-rockerhi: #3c4049;
--color-ttg26-rockerhi: oklch(0.36 0.008 265);
--color-ttg26-rockerlo: #2c2f35;
--color-ttg26-rockerlo: oklch(0.29 0.007 265);
--color-ttg26-rockerdk: #22252a;
--color-ttg26-rockerdk: oklch(0.25 0.006 265);
--color-ttg26-dim: #8b919d;
--color-ttg26-dim: oklch(0.65 0.012 265);
--color-ttg26-lit: #dde2ea;
--color-ttg26-lit: oklch(0.91 0.008 265);
--color-ttg26-lamp: #ff4a3d;
--color-ttg26-lamp: oklch(0.65 0.22 27);
--color-ttg26-lampdark: #3d2426;
--color-ttg26-lampdark: oklch(0.29 0.03 20);
--color-ttg26-tag: #c2c7d0;
--color-ttg26-tag: oklch(0.83 0.008 265);
--color-ttg26-tagink: #1e2128;
--color-ttg26-tagink: oklch(0.24 0.008 265);
--color-ttg26-mute: #7c828c;
--color-ttg26-mute: oklch(0.6 0.01 265);
--color-ttg26-focus: #6cb6f0;
--color-ttg26-focus: oklch(0.74 0.14 235);
--font-ttg26-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-26 {
width: 100%;
min-height: 100svh;
}
```How this works
Rotation plus shading makes a seesaw. The rocker holds I and O in a two-row grid and tips -16deg (O pressed in) or 16deg (I pressed in) inside a perspective well; simultaneously its gradient flips direction so the depressed half darkens. Either cue alone reads as ambiguous — together they read as a physical throw.
Engraving is one text-shadow pair. Dark above, light below. It is the oldest trick in skeuomorphism and still the cheapest: two shadows, no assets, and it scales with the font.
The lamp is the state's plain-language signal. A ±16° tip is subtle in a photograph; a lit red pilot is not. It reads the state through has-checked: on the panel, since it is a cousin of the input rather than a sibling.
Make it yours
- Legends: I/O is the IEC standard, but RUN/STOP or a power glyph work — keep it to one to four characters.
- Chunkier throw: ±22°.
- Green pilot for run-state; red conventionally means power or fault.
- Add a mechanical thunk with
navigator.vibrate?.(20)on change.
Gotchas — read before shipping
perspective-*on the WELL, not the rocker, or the halves do not foreshorten and the tip looks like a squash.- The engraved shadow must flip with the light: dark above on the recessed half, light below on the raised one.
- Keep the whole rocker one hit target. Separate I and O click zones break the checkbox contract and give you two controls that disagree.
- Steel grain at 2px intervals can moiré on scaled displays — keep the repeat above 3px if you scale the panel up.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
3D transforms and repeating gradients are universal; only the pilot lamp uses :has() (Firefox 121+) and it degrades to permanently unlit.