22 / 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 Rotary Knob Toggle with Brushed-Metal Conic Gradient
A machined aluminium knob that twists between OFF and ON detents: brushed-metal conic sheen, a milled indicator, bezel tick marks and a pilot LED that ignites at the ON position. The checkbox IS the knob — click or press Space to twist it.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="ttg-22 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg22-bg font-ttg22-sans" aria-label="Rotary knob toggle">
<div class="relative flex items-end gap-3.5 px-6 pt-7 pb-5 rounded-[18px] bg-linear-170 from-ttg22-facehi to-ttg22-facelo shadow-[0_20px_44px_-22px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.07)] has-checked:[&_.ttg22-led]:bg-ttg22-led has-checked:[&_.ttg22-led]:shadow-[0_0_7px_var(--color-ttg22-led),0_0_16px_color-mix(in_oklab,var(--color-ttg22-led)_55%,transparent)]">
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">OFF</span>
<span class="relative grid place-items-center w-26 h-26 rounded-full [background:radial-gradient(circle,var(--color-ttg22-wellhi)_58%,var(--color-ttg22-wellmid)_60%,var(--color-ttg22-welllo)_100%)] shadow-[inset_0_2px_6px_oklch(0_0_0/0.7)] before:content-[''] before:absolute before:bottom-1.5 before:left-3.5 before:w-0.5 before:h-[7px] before:rounded-[1px] before:bg-ttg22-tick before:rotate-[38deg] after:content-[''] after:absolute after:bottom-1.5 after:right-3.5 after:w-0.5 after:h-[7px] after:rounded-[1px] after:bg-ttg22-tick after:-rotate-[38deg]">
<input type="checkbox" id="ttg-22-sw" role="switch" aria-label="Amplifier power" class="appearance-none w-22 h-22 rounded-full relative cursor-pointer [background:radial-gradient(circle_at_32%_26%,oklch(1_0_0/0.35),transparent_46%),conic-gradient(var(--color-ttg22-mhi)_0_8%,var(--color-ttg22-mlo)_8%_16%,var(--color-ttg22-mmid)_16%_24%,var(--color-ttg22-mlo)_24%_32%,var(--color-ttg22-mhi)_32%_40%,var(--color-ttg22-mlo)_40%_48%,var(--color-ttg22-mmid)_48%_56%,var(--color-ttg22-mlo)_56%_64%,var(--color-ttg22-mhi)_64%_72%,var(--color-ttg22-mlo)_72%_80%,var(--color-ttg22-mmid)_80%_88%,var(--color-ttg22-mlo)_88%_96%,var(--color-ttg22-mhi)_96%_100%)] shadow-[0_6px_14px_oklch(0_0_0/0.6),inset_0_-3px_6px_oklch(0_0_0/0.35),inset_0_2px_3px_oklch(1_0_0/0.5)] rotate-[-32deg] transition-transform duration-[350ms] ease-[cubic-bezier(0.3,1.4,0.4,1)] checked:rotate-[32deg] active:scale-[0.97] checked:active:scale-[0.97] before:content-[''] before:absolute before:top-[7px] before:left-1/2 before:-ml-[2.5px] before:w-[5px] before:h-[22px] before:rounded-[3px] before:bg-ttg22-indicator before:shadow-[inset_0_1px_2px_oklch(0_0_0/0.8),0_1px_0_oklch(1_0_0/0.3)] focus-visible:outline-3 focus-visible:outline-ttg22-focus focus-visible:outline-offset-[5px] motion-reduce:duration-100">
</span>
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">ON</span>
<span aria-hidden="true" class="ttg22-led absolute top-3.5 right-4 w-[9px] h-[9px] rounded-full bg-ttg22-leddark shadow-[inset_0_1px_2px_oklch(0_0_0/0.7)] transition-[background-color,box-shadow] duration-250"></span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg22-mute">Machined detent · click to twist</p>
</section><section class="ttg-22 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg22-bg font-ttg22-sans" aria-label="Rotary knob toggle">
<div class="relative flex items-end gap-3.5 px-6 pt-7 pb-5 rounded-[18px] bg-linear-170 from-ttg22-facehi to-ttg22-facelo shadow-[0_20px_44px_-22px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.07)] has-checked:[&_.ttg22-led]:bg-ttg22-led has-checked:[&_.ttg22-led]:shadow-[0_0_7px_var(--color-ttg22-led),0_0_16px_color-mix(in_oklab,var(--color-ttg22-led)_55%,transparent)]">
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">OFF</span>
<span class="relative grid place-items-center w-26 h-26 rounded-full [background:radial-gradient(circle,var(--color-ttg22-wellhi)_58%,var(--color-ttg22-wellmid)_60%,var(--color-ttg22-welllo)_100%)] shadow-[inset_0_2px_6px_oklch(0_0_0/0.7)] before:content-[''] before:absolute before:bottom-1.5 before:left-3.5 before:w-0.5 before:h-[7px] before:rounded-[1px] before:bg-ttg22-tick before:rotate-[38deg] after:content-[''] after:absolute after:bottom-1.5 after:right-3.5 after:w-0.5 after:h-[7px] after:rounded-[1px] after:bg-ttg22-tick after:-rotate-[38deg]">
<input type="checkbox" id="ttg-22-sw" role="switch" aria-label="Amplifier power" class="appearance-none w-22 h-22 rounded-full relative cursor-pointer [background:radial-gradient(circle_at_32%_26%,oklch(1_0_0/0.35),transparent_46%),conic-gradient(var(--color-ttg22-mhi)_0_8%,var(--color-ttg22-mlo)_8%_16%,var(--color-ttg22-mmid)_16%_24%,var(--color-ttg22-mlo)_24%_32%,var(--color-ttg22-mhi)_32%_40%,var(--color-ttg22-mlo)_40%_48%,var(--color-ttg22-mmid)_48%_56%,var(--color-ttg22-mlo)_56%_64%,var(--color-ttg22-mhi)_64%_72%,var(--color-ttg22-mlo)_72%_80%,var(--color-ttg22-mmid)_80%_88%,var(--color-ttg22-mlo)_88%_96%,var(--color-ttg22-mhi)_96%_100%)] shadow-[0_6px_14px_oklch(0_0_0/0.6),inset_0_-3px_6px_oklch(0_0_0/0.35),inset_0_2px_3px_oklch(1_0_0/0.5)] rotate-[-32deg] transition-transform duration-[350ms] ease-[cubic-bezier(0.3,1.4,0.4,1)] checked:rotate-[32deg] active:scale-[0.97] checked:active:scale-[0.97] before:content-[''] before:absolute before:top-[7px] before:left-1/2 before:-ml-[2.5px] before:w-[5px] before:h-[22px] before:rounded-[3px] before:bg-ttg22-indicator before:shadow-[inset_0_1px_2px_oklch(0_0_0/0.8),0_1px_0_oklch(1_0_0/0.3)] focus-visible:outline-3 focus-visible:outline-ttg22-focus focus-visible:outline-offset-[5px] motion-reduce:duration-100">
</span>
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">ON</span>
<span aria-hidden="true" class="ttg22-led absolute top-3.5 right-4 w-[9px] h-[9px] rounded-full bg-ttg22-leddark shadow-[inset_0_1px_2px_oklch(0_0_0/0.7)] transition-[background-color,box-shadow] duration-250"></span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg22-mute">Machined detent · click to twist</p>
</section>@import "tailwindcss";
@theme {
--color-ttg22-bg: #24262a;
--color-ttg22-bg: oklch(0.27 0.005 265);
--color-ttg22-facehi: #34373d;
--color-ttg22-facehi: oklch(0.34 0.007 265);
--color-ttg22-facelo: #2a2c31;
--color-ttg22-facelo: oklch(0.29 0.006 265);
--color-ttg22-wellhi: #1d1f23;
--color-ttg22-wellhi: oklch(0.23 0.005 265);
--color-ttg22-wellmid: #3b3e45;
--color-ttg22-wellmid: oklch(0.37 0.007 265);
--color-ttg22-welllo: #22242a;
--color-ttg22-welllo: oklch(0.25 0.006 265);
--color-ttg22-mhi: #c2c7d1;
--color-ttg22-mhi: oklch(0.83 0.01 265);
--color-ttg22-mmid: #b3b8c2;
--color-ttg22-mmid: oklch(0.78 0.01 265);
--color-ttg22-mlo: #8d939e;
--color-ttg22-mlo: oklch(0.65 0.012 265);
--color-ttg22-indicator: #1e2027;
--color-ttg22-indicator: oklch(0.23 0.008 265);
--color-ttg22-tick: #8f95a1;
--color-ttg22-tick: oklch(0.66 0.012 265);
--color-ttg22-legend: #a2a8b4;
--color-ttg22-legend: oklch(0.73 0.012 265);
--color-ttg22-led: #ff5a48;
--color-ttg22-led: oklch(0.7 0.2 25);
--color-ttg22-leddark: #3a3026;
--color-ttg22-leddark: oklch(0.3 0.02 60);
--color-ttg22-mute: #7e848f;
--color-ttg22-mute: oklch(0.6 0.012 265);
--color-ttg22-focus: #6cb6f0;
--color-ttg22-focus: oklch(0.74 0.14 235);
--font-ttg22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-22 {
width: 100%;
min-height: 100svh;
}
.ttg-22 input[type="checkbox"] {
-webkit-appearance: none;
}@import "tailwindcss";
@theme {
--color-ttg22-bg: #24262a;
--color-ttg22-bg: oklch(0.27 0.005 265);
--color-ttg22-facehi: #34373d;
--color-ttg22-facehi: oklch(0.34 0.007 265);
--color-ttg22-facelo: #2a2c31;
--color-ttg22-facelo: oklch(0.29 0.006 265);
--color-ttg22-wellhi: #1d1f23;
--color-ttg22-wellhi: oklch(0.23 0.005 265);
--color-ttg22-wellmid: #3b3e45;
--color-ttg22-wellmid: oklch(0.37 0.007 265);
--color-ttg22-welllo: #22242a;
--color-ttg22-welllo: oklch(0.25 0.006 265);
--color-ttg22-mhi: #c2c7d1;
--color-ttg22-mhi: oklch(0.83 0.01 265);
--color-ttg22-mmid: #b3b8c2;
--color-ttg22-mmid: oklch(0.78 0.01 265);
--color-ttg22-mlo: #8d939e;
--color-ttg22-mlo: oklch(0.65 0.012 265);
--color-ttg22-indicator: #1e2027;
--color-ttg22-indicator: oklch(0.23 0.008 265);
--color-ttg22-tick: #8f95a1;
--color-ttg22-tick: oklch(0.66 0.012 265);
--color-ttg22-legend: #a2a8b4;
--color-ttg22-legend: oklch(0.73 0.012 265);
--color-ttg22-led: #ff5a48;
--color-ttg22-led: oklch(0.7 0.2 25);
--color-ttg22-leddark: #3a3026;
--color-ttg22-leddark: oklch(0.3 0.02 60);
--color-ttg22-mute: #7e848f;
--color-ttg22-mute: oklch(0.6 0.012 265);
--color-ttg22-focus: #6cb6f0;
--color-ttg22-focus: oklch(0.74 0.14 235);
--font-ttg22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-22 {
width: 100%;
min-height: 100svh;
}
.ttg-22 input[type="checkbox"] {
-webkit-appearance: none;
}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-ttg22-bg: #24262a;
--color-ttg22-bg: oklch(0.27 0.005 265);
--color-ttg22-facehi: #34373d;
--color-ttg22-facehi: oklch(0.34 0.007 265);
--color-ttg22-facelo: #2a2c31;
--color-ttg22-facelo: oklch(0.29 0.006 265);
--color-ttg22-wellhi: #1d1f23;
--color-ttg22-wellhi: oklch(0.23 0.005 265);
--color-ttg22-wellmid: #3b3e45;
--color-ttg22-wellmid: oklch(0.37 0.007 265);
--color-ttg22-welllo: #22242a;
--color-ttg22-welllo: oklch(0.25 0.006 265);
--color-ttg22-mhi: #c2c7d1;
--color-ttg22-mhi: oklch(0.83 0.01 265);
--color-ttg22-mmid: #b3b8c2;
--color-ttg22-mmid: oklch(0.78 0.01 265);
--color-ttg22-mlo: #8d939e;
--color-ttg22-mlo: oklch(0.65 0.012 265);
--color-ttg22-indicator: #1e2027;
--color-ttg22-indicator: oklch(0.23 0.008 265);
--color-ttg22-tick: #8f95a1;
--color-ttg22-tick: oklch(0.66 0.012 265);
--color-ttg22-legend: #a2a8b4;
--color-ttg22-legend: oklch(0.73 0.012 265);
--color-ttg22-led: #ff5a48;
--color-ttg22-led: oklch(0.7 0.2 25);
--color-ttg22-leddark: #3a3026;
--color-ttg22-leddark: oklch(0.3 0.02 60);
--color-ttg22-mute: #7e848f;
--color-ttg22-mute: oklch(0.6 0.012 265);
--color-ttg22-focus: #6cb6f0;
--color-ttg22-focus: oklch(0.74 0.14 235);
--font-ttg22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-22 {
width: 100%;
min-height: 100svh;
}
.ttg-22 input[type="checkbox"] {
-webkit-appearance: none;
}@import "tailwindcss";
@theme {
--color-ttg22-bg: #24262a;
--color-ttg22-bg: oklch(0.27 0.005 265);
--color-ttg22-facehi: #34373d;
--color-ttg22-facehi: oklch(0.34 0.007 265);
--color-ttg22-facelo: #2a2c31;
--color-ttg22-facelo: oklch(0.29 0.006 265);
--color-ttg22-wellhi: #1d1f23;
--color-ttg22-wellhi: oklch(0.23 0.005 265);
--color-ttg22-wellmid: #3b3e45;
--color-ttg22-wellmid: oklch(0.37 0.007 265);
--color-ttg22-welllo: #22242a;
--color-ttg22-welllo: oklch(0.25 0.006 265);
--color-ttg22-mhi: #c2c7d1;
--color-ttg22-mhi: oklch(0.83 0.01 265);
--color-ttg22-mmid: #b3b8c2;
--color-ttg22-mmid: oklch(0.78 0.01 265);
--color-ttg22-mlo: #8d939e;
--color-ttg22-mlo: oklch(0.65 0.012 265);
--color-ttg22-indicator: #1e2027;
--color-ttg22-indicator: oklch(0.23 0.008 265);
--color-ttg22-tick: #8f95a1;
--color-ttg22-tick: oklch(0.66 0.012 265);
--color-ttg22-legend: #a2a8b4;
--color-ttg22-legend: oklch(0.73 0.012 265);
--color-ttg22-led: #ff5a48;
--color-ttg22-led: oklch(0.7 0.2 25);
--color-ttg22-leddark: #3a3026;
--color-ttg22-leddark: oklch(0.3 0.02 60);
--color-ttg22-mute: #7e848f;
--color-ttg22-mute: oklch(0.6 0.012 265);
--color-ttg22-focus: #6cb6f0;
--color-ttg22-focus: oklch(0.74 0.14 235);
--font-ttg22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-22 {
width: 100%;
min-height: 100svh;
}
.ttg-22 input[type="checkbox"] {
-webkit-appearance: none;
}<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&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&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Thirteen conic stops in one arbitrary
[background:...]is unapologetically ugly in a class list, and still correct: it is a single texture, it belongs to exactly one element, and every stop reads a named metal token so the whole finish can be restyled from@theme. checked:rotate-[32deg]on the input rather than on a child is what makes the machining turn. Tailwind's rotate utility composes withactive:scale-[0.97]through its transform variables, so the press does not clobber the angle — something the CSS original had to restate by hand in two compound rules.- The two bezel ticks are
before:andafter:on the well, which keeps the rotating input free of children it would drag around with it. - UI change from the CSS original: the OFF/ON legends lifted from
#7d828ctooklch(0.73)(6.8:1 on the faceplate, from 3.2:1), the caption likewise, and the metal stops were regraded in oklch so the brushed sheen keeps even perceptual spacing instead of banding at the dark 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 Rotary Knob Toggle with Brushed-Metal Conic Gradient
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-rotary-knob-toggle-brushed-metal-conic-gradient/
A machined aluminium knob that twists between OFF and ON detents: brushed-metal conic sheen, a milled indicator, bezel tick marks and a pilot LED that ignites at the ON position. The checkbox IS the knob — click or press Space to twist it.
## HTML
```html
<section class="ttg-22 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg22-bg font-ttg22-sans" aria-label="Rotary knob toggle">
<div class="relative flex items-end gap-3.5 px-6 pt-7 pb-5 rounded-[18px] bg-linear-170 from-ttg22-facehi to-ttg22-facelo shadow-[0_20px_44px_-22px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.07)] has-checked:[&_.ttg22-led]:bg-ttg22-led has-checked:[&_.ttg22-led]:shadow-[0_0_7px_var(--color-ttg22-led),0_0_16px_color-mix(in_oklab,var(--color-ttg22-led)_55%,transparent)]">
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">OFF</span>
<span class="relative grid place-items-center w-26 h-26 rounded-full [background:radial-gradient(circle,var(--color-ttg22-wellhi)_58%,var(--color-ttg22-wellmid)_60%,var(--color-ttg22-welllo)_100%)] shadow-[inset_0_2px_6px_oklch(0_0_0/0.7)] before:content-[''] before:absolute before:bottom-1.5 before:left-3.5 before:w-0.5 before:h-[7px] before:rounded-[1px] before:bg-ttg22-tick before:rotate-[38deg] after:content-[''] after:absolute after:bottom-1.5 after:right-3.5 after:w-0.5 after:h-[7px] after:rounded-[1px] after:bg-ttg22-tick after:-rotate-[38deg]">
<input type="checkbox" id="ttg-22-sw" role="switch" aria-label="Amplifier power" class="appearance-none w-22 h-22 rounded-full relative cursor-pointer [background:radial-gradient(circle_at_32%_26%,oklch(1_0_0/0.35),transparent_46%),conic-gradient(var(--color-ttg22-mhi)_0_8%,var(--color-ttg22-mlo)_8%_16%,var(--color-ttg22-mmid)_16%_24%,var(--color-ttg22-mlo)_24%_32%,var(--color-ttg22-mhi)_32%_40%,var(--color-ttg22-mlo)_40%_48%,var(--color-ttg22-mmid)_48%_56%,var(--color-ttg22-mlo)_56%_64%,var(--color-ttg22-mhi)_64%_72%,var(--color-ttg22-mlo)_72%_80%,var(--color-ttg22-mmid)_80%_88%,var(--color-ttg22-mlo)_88%_96%,var(--color-ttg22-mhi)_96%_100%)] shadow-[0_6px_14px_oklch(0_0_0/0.6),inset_0_-3px_6px_oklch(0_0_0/0.35),inset_0_2px_3px_oklch(1_0_0/0.5)] rotate-[-32deg] transition-transform duration-[350ms] ease-[cubic-bezier(0.3,1.4,0.4,1)] checked:rotate-[32deg] active:scale-[0.97] checked:active:scale-[0.97] before:content-[''] before:absolute before:top-[7px] before:left-1/2 before:-ml-[2.5px] before:w-[5px] before:h-[22px] before:rounded-[3px] before:bg-ttg22-indicator before:shadow-[inset_0_1px_2px_oklch(0_0_0/0.8),0_1px_0_oklch(1_0_0/0.3)] focus-visible:outline-3 focus-visible:outline-ttg22-focus focus-visible:outline-offset-[5px] motion-reduce:duration-100">
</span>
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">ON</span>
<span aria-hidden="true" class="ttg22-led absolute top-3.5 right-4 w-[9px] h-[9px] rounded-full bg-ttg22-leddark shadow-[inset_0_1px_2px_oklch(0_0_0/0.7)] transition-[background-color,box-shadow] duration-250"></span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg22-mute">Machined detent · click to twist</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg22-bg: #24262a;
--color-ttg22-bg: oklch(0.27 0.005 265);
--color-ttg22-facehi: #34373d;
--color-ttg22-facehi: oklch(0.34 0.007 265);
--color-ttg22-facelo: #2a2c31;
--color-ttg22-facelo: oklch(0.29 0.006 265);
--color-ttg22-wellhi: #1d1f23;
--color-ttg22-wellhi: oklch(0.23 0.005 265);
--color-ttg22-wellmid: #3b3e45;
--color-ttg22-wellmid: oklch(0.37 0.007 265);
--color-ttg22-welllo: #22242a;
--color-ttg22-welllo: oklch(0.25 0.006 265);
--color-ttg22-mhi: #c2c7d1;
--color-ttg22-mhi: oklch(0.83 0.01 265);
--color-ttg22-mmid: #b3b8c2;
--color-ttg22-mmid: oklch(0.78 0.01 265);
--color-ttg22-mlo: #8d939e;
--color-ttg22-mlo: oklch(0.65 0.012 265);
--color-ttg22-indicator: #1e2027;
--color-ttg22-indicator: oklch(0.23 0.008 265);
--color-ttg22-tick: #8f95a1;
--color-ttg22-tick: oklch(0.66 0.012 265);
--color-ttg22-legend: #a2a8b4;
--color-ttg22-legend: oklch(0.73 0.012 265);
--color-ttg22-led: #ff5a48;
--color-ttg22-led: oklch(0.7 0.2 25);
--color-ttg22-leddark: #3a3026;
--color-ttg22-leddark: oklch(0.3 0.02 60);
--color-ttg22-mute: #7e848f;
--color-ttg22-mute: oklch(0.6 0.012 265);
--color-ttg22-focus: #6cb6f0;
--color-ttg22-focus: oklch(0.74 0.14 235);
--font-ttg22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-22 {
width: 100%;
min-height: 100svh;
}
.ttg-22 input[type="checkbox"] {
-webkit-appearance: none;
}
```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 Rotary Knob Toggle with Brushed-Metal Conic Gradient
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-rotary-knob-toggle-brushed-metal-conic-gradient/
A machined aluminium knob that twists between OFF and ON detents: brushed-metal conic sheen, a milled indicator, bezel tick marks and a pilot LED that ignites at the ON position. The checkbox IS the knob — click or press Space to twist it.
## HTML
```html
<section class="ttg-22 w-full min-h-svh flex flex-col items-center justify-center gap-8 px-5 py-14 bg-ttg22-bg font-ttg22-sans" aria-label="Rotary knob toggle">
<div class="relative flex items-end gap-3.5 px-6 pt-7 pb-5 rounded-[18px] bg-linear-170 from-ttg22-facehi to-ttg22-facelo shadow-[0_20px_44px_-22px_oklch(0_0_0/0.9),inset_0_1px_0_oklch(1_0_0/0.07)] has-checked:[&_.ttg22-led]:bg-ttg22-led has-checked:[&_.ttg22-led]:shadow-[0_0_7px_var(--color-ttg22-led),0_0_16px_color-mix(in_oklab,var(--color-ttg22-led)_55%,transparent)]">
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">OFF</span>
<span class="relative grid place-items-center w-26 h-26 rounded-full [background:radial-gradient(circle,var(--color-ttg22-wellhi)_58%,var(--color-ttg22-wellmid)_60%,var(--color-ttg22-welllo)_100%)] shadow-[inset_0_2px_6px_oklch(0_0_0/0.7)] before:content-[''] before:absolute before:bottom-1.5 before:left-3.5 before:w-0.5 before:h-[7px] before:rounded-[1px] before:bg-ttg22-tick before:rotate-[38deg] after:content-[''] after:absolute after:bottom-1.5 after:right-3.5 after:w-0.5 after:h-[7px] after:rounded-[1px] after:bg-ttg22-tick after:-rotate-[38deg]">
<input type="checkbox" id="ttg-22-sw" role="switch" aria-label="Amplifier power" class="appearance-none w-22 h-22 rounded-full relative cursor-pointer [background:radial-gradient(circle_at_32%_26%,oklch(1_0_0/0.35),transparent_46%),conic-gradient(var(--color-ttg22-mhi)_0_8%,var(--color-ttg22-mlo)_8%_16%,var(--color-ttg22-mmid)_16%_24%,var(--color-ttg22-mlo)_24%_32%,var(--color-ttg22-mhi)_32%_40%,var(--color-ttg22-mlo)_40%_48%,var(--color-ttg22-mmid)_48%_56%,var(--color-ttg22-mlo)_56%_64%,var(--color-ttg22-mhi)_64%_72%,var(--color-ttg22-mlo)_72%_80%,var(--color-ttg22-mmid)_80%_88%,var(--color-ttg22-mlo)_88%_96%,var(--color-ttg22-mhi)_96%_100%)] shadow-[0_6px_14px_oklch(0_0_0/0.6),inset_0_-3px_6px_oklch(0_0_0/0.35),inset_0_2px_3px_oklch(1_0_0/0.5)] rotate-[-32deg] transition-transform duration-[350ms] ease-[cubic-bezier(0.3,1.4,0.4,1)] checked:rotate-[32deg] active:scale-[0.97] checked:active:scale-[0.97] before:content-[''] before:absolute before:top-[7px] before:left-1/2 before:-ml-[2.5px] before:w-[5px] before:h-[22px] before:rounded-[3px] before:bg-ttg22-indicator before:shadow-[inset_0_1px_2px_oklch(0_0_0/0.8),0_1px_0_oklch(1_0_0/0.3)] focus-visible:outline-3 focus-visible:outline-ttg22-focus focus-visible:outline-offset-[5px] motion-reduce:duration-100">
</span>
<span aria-hidden="true" class="pb-8.5 text-[11px] font-bold tracking-[0.18em] text-ttg22-legend">ON</span>
<span aria-hidden="true" class="ttg22-led absolute top-3.5 right-4 w-[9px] h-[9px] rounded-full bg-ttg22-leddark shadow-[inset_0_1px_2px_oklch(0_0_0/0.7)] transition-[background-color,box-shadow] duration-250"></span>
</div>
<p class="text-[11px] tracking-[0.16em] uppercase text-ttg22-mute">Machined detent · click to twist</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg22-bg: #24262a;
--color-ttg22-bg: oklch(0.27 0.005 265);
--color-ttg22-facehi: #34373d;
--color-ttg22-facehi: oklch(0.34 0.007 265);
--color-ttg22-facelo: #2a2c31;
--color-ttg22-facelo: oklch(0.29 0.006 265);
--color-ttg22-wellhi: #1d1f23;
--color-ttg22-wellhi: oklch(0.23 0.005 265);
--color-ttg22-wellmid: #3b3e45;
--color-ttg22-wellmid: oklch(0.37 0.007 265);
--color-ttg22-welllo: #22242a;
--color-ttg22-welllo: oklch(0.25 0.006 265);
--color-ttg22-mhi: #c2c7d1;
--color-ttg22-mhi: oklch(0.83 0.01 265);
--color-ttg22-mmid: #b3b8c2;
--color-ttg22-mmid: oklch(0.78 0.01 265);
--color-ttg22-mlo: #8d939e;
--color-ttg22-mlo: oklch(0.65 0.012 265);
--color-ttg22-indicator: #1e2027;
--color-ttg22-indicator: oklch(0.23 0.008 265);
--color-ttg22-tick: #8f95a1;
--color-ttg22-tick: oklch(0.66 0.012 265);
--color-ttg22-legend: #a2a8b4;
--color-ttg22-legend: oklch(0.73 0.012 265);
--color-ttg22-led: #ff5a48;
--color-ttg22-led: oklch(0.7 0.2 25);
--color-ttg22-leddark: #3a3026;
--color-ttg22-leddark: oklch(0.3 0.02 60);
--color-ttg22-mute: #7e848f;
--color-ttg22-mute: oklch(0.6 0.012 265);
--color-ttg22-focus: #6cb6f0;
--color-ttg22-focus: oklch(0.74 0.14 235);
--font-ttg22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
.ttg-22 {
width: 100%;
min-height: 100svh;
}
.ttg-22 input[type="checkbox"] {
-webkit-appearance: none;
}
```How this works
Rotate the whole control, not the pointer. A thirteen-stop conic gradient under a radial highlight gives brushed aluminium; rotating the input turns the texture with the indicator line. Rotating only a pointer over a static texture is the tell that makes a knob look like a sticker.
Legends and ticks must not turn. OFF, ON and the two bezel ticks live on the static wrapper. This is the constraint that shapes the markup: anything that stays upright has to be outside the element that rotates.
The LED is the state's second signal. Knob angle is subtle at a glance, so a pilot lamp with a two-layer glow confirms it — and because it is a sibling, it reads the state through has-checked: on the unit.
Make it yours
- Wider throw: ±45° for a heavier industrial feel.
- Recolour the lamp through
--color-ttg22-led; both glow layers follow. - More detents: the ticks are positioned spans, so add as many as the bezel fits.
- Black anodise: darken every conic stop and keep the radial highlight untouched.
Gotchas — read before shipping
- Rotate the input itself. A static texture under a moving line is the single most common knob mistake.
- Legends and ticks belong outside the rotating element, or they turn with it.
- Round controls need a generous hit area — the whole 88px disc is clickable here, not just the indicator.
- A conic gradient with thirteen stops is a real paint cost at large sizes; keep the knob under ~120px or pre-render it.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
conic-gradient and transforms are supported in all evergreen browsers; without conic support the knob falls back to a flat disc whose indicator still rotates correctly.