23 / 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 iOS Settings List with Grouped Toggle Rows
The whole iOS Settings context, not just the switch: a grouped light list with inset hairlines, coloured glyph tiles and three native-geometry toggles — the pattern to copy when you need an entire preferences screen, section header and footnote included.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="ttg-23 w-full min-h-svh grid place-items-center px-5 py-14 bg-ttg23-bg font-ttg23-sans" aria-label="iOS settings list with toggles">
<div class="w-[min(370px,100%)]">
<p class="mx-4 mb-2 text-[13px] uppercase tracking-[0.05em] text-ttg23-mute">Notifications</p>
<div class="rounded-xl bg-white overflow-hidden">
<label style="--g:oklch(0.62 0.22 27)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◗</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Allow Notifications</span>
<input type="checkbox" role="switch" checked aria-label="Allow Notifications" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.58 0.2 258)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◍</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Time Sensitive</span>
<input type="checkbox" role="switch" checked aria-label="Time Sensitive" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.6 0.2 310)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◔</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Scheduled Summary</span>
<input type="checkbox" role="switch" aria-label="Scheduled Summary" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
</div>
<p class="mx-4 mt-2 text-[13px] leading-[1.45] text-ttg23-mute">Time Sensitive notifications are delivered immediately and stay on the Lock Screen for an hour.</p>
</div>
</section><section class="ttg-23 w-full min-h-svh grid place-items-center px-5 py-14 bg-ttg23-bg font-ttg23-sans" aria-label="iOS settings list with toggles">
<div class="w-[min(370px,100%)]">
<p class="mx-4 mb-2 text-[13px] uppercase tracking-[0.05em] text-ttg23-mute">Notifications</p>
<div class="rounded-xl bg-white overflow-hidden">
<label style="--g:oklch(0.62 0.22 27)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◗</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Allow Notifications</span>
<input type="checkbox" role="switch" checked aria-label="Allow Notifications" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.58 0.2 258)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◍</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Time Sensitive</span>
<input type="checkbox" role="switch" checked aria-label="Time Sensitive" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.6 0.2 310)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◔</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Scheduled Summary</span>
<input type="checkbox" role="switch" aria-label="Scheduled Summary" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
</div>
<p class="mx-4 mt-2 text-[13px] leading-[1.45] text-ttg23-mute">Time Sensitive notifications are delivered immediately and stay on the Lock Screen for an hour.</p>
</div>
</section>@import "tailwindcss";
@theme {
--color-ttg23-bg: #f1f1f6;
--color-ttg23-bg: oklch(0.96 0.004 285);
--color-ttg23-tint: #f8f8fb;
--color-ttg23-tint: oklch(0.98 0.003 285);
--color-ttg23-hair: #c8c8cc;
--color-ttg23-hair: oklch(0.83 0.004 285);
--color-ttg23-ink: #0b0b0d;
--color-ttg23-ink: oklch(0.15 0.004 285);
--color-ttg23-mute: #62626a;
--color-ttg23-mute: oklch(0.51 0.008 285);
--color-ttg23-off: #e6e6ea;
--color-ttg23-off: oklch(0.93 0.003 285);
--color-ttg23-on: #2fbf5b;
--color-ttg23-on: oklch(0.72 0.18 149);
--color-ttg23-focus: #0a84ff;
--color-ttg23-focus: oklch(0.62 0.2 256);
--font-ttg23-sans: 'Plus Jakarta Sans', -apple-system, system-ui, sans-serif;
}
.ttg-23 {
width: 100%;
min-height: 100svh;
}
.ttg-23 input[type="checkbox"] {
-webkit-appearance: none;
}@import "tailwindcss";
@theme {
--color-ttg23-bg: #f1f1f6;
--color-ttg23-bg: oklch(0.96 0.004 285);
--color-ttg23-tint: #f8f8fb;
--color-ttg23-tint: oklch(0.98 0.003 285);
--color-ttg23-hair: #c8c8cc;
--color-ttg23-hair: oklch(0.83 0.004 285);
--color-ttg23-ink: #0b0b0d;
--color-ttg23-ink: oklch(0.15 0.004 285);
--color-ttg23-mute: #62626a;
--color-ttg23-mute: oklch(0.51 0.008 285);
--color-ttg23-off: #e6e6ea;
--color-ttg23-off: oklch(0.93 0.003 285);
--color-ttg23-on: #2fbf5b;
--color-ttg23-on: oklch(0.72 0.18 149);
--color-ttg23-focus: #0a84ff;
--color-ttg23-focus: oklch(0.62 0.2 256);
--font-ttg23-sans: 'Plus Jakarta Sans', -apple-system, system-ui, sans-serif;
}
.ttg-23 {
width: 100%;
min-height: 100svh;
}
.ttg-23 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-ttg23-bg: #f1f1f6;
--color-ttg23-bg: oklch(0.96 0.004 285);
--color-ttg23-tint: #f8f8fb;
--color-ttg23-tint: oklch(0.98 0.003 285);
--color-ttg23-hair: #c8c8cc;
--color-ttg23-hair: oklch(0.83 0.004 285);
--color-ttg23-ink: #0b0b0d;
--color-ttg23-ink: oklch(0.15 0.004 285);
--color-ttg23-mute: #62626a;
--color-ttg23-mute: oklch(0.51 0.008 285);
--color-ttg23-off: #e6e6ea;
--color-ttg23-off: oklch(0.93 0.003 285);
--color-ttg23-on: #2fbf5b;
--color-ttg23-on: oklch(0.72 0.18 149);
--color-ttg23-focus: #0a84ff;
--color-ttg23-focus: oklch(0.62 0.2 256);
--font-ttg23-sans: 'Plus Jakarta Sans', -apple-system, system-ui, sans-serif;
}
.ttg-23 {
width: 100%;
min-height: 100svh;
}
.ttg-23 input[type="checkbox"] {
-webkit-appearance: none;
}@import "tailwindcss";
@theme {
--color-ttg23-bg: #f1f1f6;
--color-ttg23-bg: oklch(0.96 0.004 285);
--color-ttg23-tint: #f8f8fb;
--color-ttg23-tint: oklch(0.98 0.003 285);
--color-ttg23-hair: #c8c8cc;
--color-ttg23-hair: oklch(0.83 0.004 285);
--color-ttg23-ink: #0b0b0d;
--color-ttg23-ink: oklch(0.15 0.004 285);
--color-ttg23-mute: #62626a;
--color-ttg23-mute: oklch(0.51 0.008 285);
--color-ttg23-off: #e6e6ea;
--color-ttg23-off: oklch(0.93 0.003 285);
--color-ttg23-on: #2fbf5b;
--color-ttg23-on: oklch(0.72 0.18 149);
--color-ttg23-focus: #0a84ff;
--color-ttg23-focus: oklch(0.62 0.2 256);
--font-ttg23-sans: 'Plus Jakarta Sans', -apple-system, system-ui, sans-serif;
}
.ttg-23 {
width: 100%;
min-height: 100svh;
}
.ttg-23 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.
not-last:after:*is v4's answer to:not(:last-child)::after, and stacking a structural variant with a pseudo-element variant on seven utilities is genuinely verbose — but it keeps the hairline's inset beside the glyph width that determines it, which is the number people actually get wrong.bg-(--g)reads an inline custom property with v4's shorthand, so three rows share one class list and differ by one inline value — the same technique as the keycaps in demo 08.- The row height is
h-13(52px) rather than the 44px floor, because that is the platform metric and the whole point of this demo is fidelity. - UI change from the CSS original: section header and footnote ink moved from
#6d6d72tooklch(0.51)for 7:1 (the footnote is real instructional copy, not decoration), rows gained a hover tint for pointer users, and the hairline was darkened slightly so it survives on non-Retina displays where a 0.5px line at#c6c6c8disappears.
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 iOS Settings List with Grouped Toggle Rows
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-ios-settings-list-grouped-toggle-rows/
The whole iOS Settings context, not just the switch: a grouped light list with inset hairlines, coloured glyph tiles and three native-geometry toggles — the pattern to copy when you need an entire preferences screen, section header and footnote included.
## HTML
```html
<section class="ttg-23 w-full min-h-svh grid place-items-center px-5 py-14 bg-ttg23-bg font-ttg23-sans" aria-label="iOS settings list with toggles">
<div class="w-[min(370px,100%)]">
<p class="mx-4 mb-2 text-[13px] uppercase tracking-[0.05em] text-ttg23-mute">Notifications</p>
<div class="rounded-xl bg-white overflow-hidden">
<label style="--g:oklch(0.62 0.22 27)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◗</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Allow Notifications</span>
<input type="checkbox" role="switch" checked aria-label="Allow Notifications" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.58 0.2 258)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◍</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Time Sensitive</span>
<input type="checkbox" role="switch" checked aria-label="Time Sensitive" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.6 0.2 310)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◔</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Scheduled Summary</span>
<input type="checkbox" role="switch" aria-label="Scheduled Summary" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
</div>
<p class="mx-4 mt-2 text-[13px] leading-[1.45] text-ttg23-mute">Time Sensitive notifications are delivered immediately and stay on the Lock Screen for an hour.</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg23-bg: #f1f1f6;
--color-ttg23-bg: oklch(0.96 0.004 285);
--color-ttg23-tint: #f8f8fb;
--color-ttg23-tint: oklch(0.98 0.003 285);
--color-ttg23-hair: #c8c8cc;
--color-ttg23-hair: oklch(0.83 0.004 285);
--color-ttg23-ink: #0b0b0d;
--color-ttg23-ink: oklch(0.15 0.004 285);
--color-ttg23-mute: #62626a;
--color-ttg23-mute: oklch(0.51 0.008 285);
--color-ttg23-off: #e6e6ea;
--color-ttg23-off: oklch(0.93 0.003 285);
--color-ttg23-on: #2fbf5b;
--color-ttg23-on: oklch(0.72 0.18 149);
--color-ttg23-focus: #0a84ff;
--color-ttg23-focus: oklch(0.62 0.2 256);
--font-ttg23-sans: 'Plus Jakarta Sans', -apple-system, system-ui, sans-serif;
}
.ttg-23 {
width: 100%;
min-height: 100svh;
}
.ttg-23 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 iOS Settings List with Grouped Toggle Rows
Source: https://codefronts.com/components/tailwind-css-toggles-switches/tailwind-ios-settings-list-grouped-toggle-rows/
The whole iOS Settings context, not just the switch: a grouped light list with inset hairlines, coloured glyph tiles and three native-geometry toggles — the pattern to copy when you need an entire preferences screen, section header and footnote included.
## HTML
```html
<section class="ttg-23 w-full min-h-svh grid place-items-center px-5 py-14 bg-ttg23-bg font-ttg23-sans" aria-label="iOS settings list with toggles">
<div class="w-[min(370px,100%)]">
<p class="mx-4 mb-2 text-[13px] uppercase tracking-[0.05em] text-ttg23-mute">Notifications</p>
<div class="rounded-xl bg-white overflow-hidden">
<label style="--g:oklch(0.62 0.22 27)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◗</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Allow Notifications</span>
<input type="checkbox" role="switch" checked aria-label="Allow Notifications" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.58 0.2 258)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint not-last:after:content-[''] not-last:after:absolute not-last:after:left-[58px] not-last:after:right-0 not-last:after:bottom-0 not-last:after:h-px not-last:after:bg-ttg23-hair">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◍</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Time Sensitive</span>
<input type="checkbox" role="switch" checked aria-label="Time Sensitive" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
<label style="--g:oklch(0.6 0.2 310)" class="relative flex items-center gap-3 h-13 px-4 cursor-pointer transition-colors duration-150 hover:bg-ttg23-tint">
<span aria-hidden="true" class="shrink-0 grid place-items-center w-7.5 h-7.5 rounded-[7px] bg-(--g) text-white text-[15px]">◔</span>
<span class="flex-1 text-[16px] text-ttg23-ink">Scheduled Summary</span>
<input type="checkbox" role="switch" aria-label="Scheduled Summary" class="appearance-none shrink-0 w-[51px] h-[31px] rounded-2xl bg-ttg23-off relative cursor-pointer transition-colors duration-300 before:content-[''] before:absolute before:top-0.5 before:left-0.5 before:w-[27px] before:h-[27px] before:rounded-full before:bg-white before:shadow-[0_3px_8px_oklch(0_0_0/0.15),0_1px_1px_oklch(0_0_0/0.16)] before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.2,0.9,0.25,1.05)] checked:bg-ttg23-on checked:before:translate-x-5 focus-visible:outline-3 focus-visible:outline-ttg23-focus focus-visible:outline-offset-2 motion-reduce:transition-none motion-reduce:before:transition-none">
</label>
</div>
<p class="mx-4 mt-2 text-[13px] leading-[1.45] text-ttg23-mute">Time Sensitive notifications are delivered immediately and stay on the Lock Screen for an hour.</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttg23-bg: #f1f1f6;
--color-ttg23-bg: oklch(0.96 0.004 285);
--color-ttg23-tint: #f8f8fb;
--color-ttg23-tint: oklch(0.98 0.003 285);
--color-ttg23-hair: #c8c8cc;
--color-ttg23-hair: oklch(0.83 0.004 285);
--color-ttg23-ink: #0b0b0d;
--color-ttg23-ink: oklch(0.15 0.004 285);
--color-ttg23-mute: #62626a;
--color-ttg23-mute: oklch(0.51 0.008 285);
--color-ttg23-off: #e6e6ea;
--color-ttg23-off: oklch(0.93 0.003 285);
--color-ttg23-on: #2fbf5b;
--color-ttg23-on: oklch(0.72 0.18 149);
--color-ttg23-focus: #0a84ff;
--color-ttg23-focus: oklch(0.62 0.2 256);
--font-ttg23-sans: 'Plus Jakarta Sans', -apple-system, system-ui, sans-serif;
}
.ttg-23 {
width: 100%;
min-height: 100svh;
}
.ttg-23 input[type="checkbox"] {
-webkit-appearance: none;
}
```How this works
The group is one card, the rows are labels. A white rounded-xl overflow-hidden container on the iOS system grey, with an uppercase section header above and a footnote below. Each row is a label containing a glyph tile, a name and the same appearance-none switch as demo 01, so tapping anywhere on the row toggles.
Hairlines are pseudo-elements, inset deliberately. not-last:after:* draws a 0.5px-equivalent line starting at 58px — past the glyph column. Full-width separators are the single clearest tell of a non-native settings list.
Switch geometry is exact. 51×31 with a 27px thumb and 20px travel. Scaled-down iOS switches read as knock-offs immediately, so this is the one demo where the numbers are not open to taste.
Make it yours
- Add rows by copying one label — hairlines and corner radii self-adjust.
- Replace the glyph characters with SF-Symbols-style SVGs inside the same 30px rounded square.
- Dark variant: black page,
oklch(0.22)cards,oklch(0.32)hairlines — token swap only. - macOS density: drop the row height to
h-10and the glyph to 22px.
Gotchas — read before shipping
- Inset the hairline past the glyph column. This is a two-character change and the whole platform read depends on it.
- The whole row is the label, so do not also make it a link — a row that both navigates and toggles is ambiguous for everyone.
- Keep 51×31. Every dimension in the iOS switch is load-bearing on recognition.
- Coloured glyph tiles carry no state; they must not be the only distinction between rows.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Same primitives as demo 01 — appearance:none checkboxes and transforms; universal in modern browsers.