12 / 29
All 29 in 29 Tailwind CSS Checkboxes
- 01Tailwind CSS Toggle Switch — iOS-Style SaaS Settings
- 02Tailwind Filter Chip Checkbox — Style Checkbox as Button
- 03Tailwind Pricing Plan Card Select — Checkbox-Style Selectable Cards
- 04Pure Tailwind CSS Accordion with Checkbox — No JavaScript
- 05Tailwind Indeterminate Checkbox — Select All with Tri-State
- 06Accessible Custom Checkbox in Tailwind CSS — WCAG Focus Ring
- 07Tailwind Slide Toggle with ON/OFF Labels — GPU translate3d
- 08Neon Glow Checkbox in Tailwind CSS — Dark Mode Gaming UI
- 09Animated SVG Checkmark in Tailwind CSS — stroke-dashoffset Draw
- 10Bouncy Checkbox Animation in Tailwind CSS — Spring cubic-bezier
- 11Glassmorphism Checkbox in Tailwind CSS — backdrop-blur Frosted Glass
- 12Neumorphism Checkbox in Tailwind CSS — Soft UI
- 13Liquid Fill Checkbox Animation in Tailwind CSS — Water Wave
- 14Rotating Ring Checkbox in Tailwind CSS — Spin-to-Check
- 15Brutalist Checkbox in Tailwind CSS — Neo-Brutalism Hard Shadow
- 16Animated Gradient Checkbox in Tailwind CSS — Rainbow Sweep
- 173D Flip Checkbox in Tailwind CSS — perspective & backface-hidden
- 18Material Ripple Checkbox in Tailwind CSS — State Layer & Wave
- 19Retro Pixel Art Checkbox in Tailwind CSS — 8-Bit Arcade Menu
- 20Tailwind CSS To-Do List Checkbox with Animated Strikethrough
- 21Gooey Blob Checkbox in Tailwind CSS — blur + contrast Filter
- 22Tailwind Dark Mode Toggle Switch — Sun & Moon, No JavaScript
- 23Pulse Ring Checkbox in Tailwind CSS — Live Status Indicator
- 24Tailwind CSS Dash-to-Check SVG Morph Checkbox
- 25Tri-State Checkbox in Tailwind CSS + JavaScript — Done / N/A / Unset
- 26Magnetic Hover Checkbox in Tailwind CSS + JavaScript
- 27Confetti Checkbox Animation in Tailwind CSS — Pure CSS Particle Burst
- 28Slide-In Label Checkbox in Tailwind CSS — Saved Tag Reveal
- 29Aurora Gradient Toggle Switch in Tailwind CSS — Premium Dark UI
Neumorphism Checkbox in Tailwind CSS — Soft UI
Soft-UI boxes that look extruded when off and pressed-in when on: the two states are two shadow tokens, shadow-tcb12-out and peer-checked:shadow-tcb12-in. Checked labels darken and a thin accent edge keeps the state legible — neumorphism's usual weakness.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcb-12 w-full min-h-svh grid place-items-center bg-tcb12-surface px-5 py-14 font-tcb12-sans text-tcb12-mut selection:bg-tcb12-acc selection:text-white" aria-label="Neumorphic checkboxes">
<div class="flex w-full max-w-[25rem] flex-col gap-1.5 rounded-[22px] bg-tcb12-surface p-5 shadow-tcb12-panel">
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only" checked><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Silent mode</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Haptic feedback</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Battery saver</span></label>
</div>
</section><section class="tcb-12 w-full min-h-svh grid place-items-center bg-tcb12-surface px-5 py-14 font-tcb12-sans text-tcb12-mut selection:bg-tcb12-acc selection:text-white" aria-label="Neumorphic checkboxes">
<div class="flex w-full max-w-[25rem] flex-col gap-1.5 rounded-[22px] bg-tcb12-surface p-5 shadow-tcb12-panel">
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only" checked><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Silent mode</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Haptic feedback</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Battery saver</span></label>
</div>
</section>@import "tailwindcss";
@theme {
--color-tcb12-surface: #e6e9ef;
--color-tcb12-surface: oklch(0.93 0.008 265);
--color-tcb12-ink: #2b3040;
--color-tcb12-ink: oklch(0.3 0.03 270);
--color-tcb12-mut: #555c6a;
--color-tcb12-mut: oklch(0.47 0.02 265);
--color-tcb12-acc: #4a5fd6;
--color-tcb12-acc: oklch(0.55 0.17 268);
--font-tcb12-sans: 'Manrope', system-ui, sans-serif;
--shadow-tcb12-panel: 9px 9px 20px #c4c9d3, -9px -9px 20px #ffffff;
--shadow-tcb12-out: 4px 4px 8px #c4c9d3, -4px -4px 8px #ffffff;
--shadow-tcb12-in: inset 4px 4px 8px #c4c9d3, inset -4px -4px 8px #ffffff, 0 0 0 1px rgb(74 95 214 / 0.35);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tcb-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tcb12-surface: #e6e9ef;
--color-tcb12-surface: oklch(0.93 0.008 265);
--color-tcb12-ink: #2b3040;
--color-tcb12-ink: oklch(0.3 0.03 270);
--color-tcb12-mut: #555c6a;
--color-tcb12-mut: oklch(0.47 0.02 265);
--color-tcb12-acc: #4a5fd6;
--color-tcb12-acc: oklch(0.55 0.17 268);
--font-tcb12-sans: 'Manrope', system-ui, sans-serif;
--shadow-tcb12-panel: 9px 9px 20px #c4c9d3, -9px -9px 20px #ffffff;
--shadow-tcb12-out: 4px 4px 8px #c4c9d3, -4px -4px 8px #ffffff;
--shadow-tcb12-in: inset 4px 4px 8px #c4c9d3, inset -4px -4px 8px #ffffff, 0 0 0 1px rgb(74 95 214 / 0.35);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tcb-12 {
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-tcb12-surface: #e6e9ef;
--color-tcb12-surface: oklch(0.93 0.008 265);
--color-tcb12-ink: #2b3040;
--color-tcb12-ink: oklch(0.3 0.03 270);
--color-tcb12-mut: #555c6a;
--color-tcb12-mut: oklch(0.47 0.02 265);
--color-tcb12-acc: #4a5fd6;
--color-tcb12-acc: oklch(0.55 0.17 268);
--font-tcb12-sans: 'Manrope', system-ui, sans-serif;
--shadow-tcb12-panel: 9px 9px 20px #c4c9d3, -9px -9px 20px #ffffff;
--shadow-tcb12-out: 4px 4px 8px #c4c9d3, -4px -4px 8px #ffffff;
--shadow-tcb12-in: inset 4px 4px 8px #c4c9d3, inset -4px -4px 8px #ffffff, 0 0 0 1px rgb(74 95 214 / 0.35);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tcb-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tcb12-surface: #e6e9ef;
--color-tcb12-surface: oklch(0.93 0.008 265);
--color-tcb12-ink: #2b3040;
--color-tcb12-ink: oklch(0.3 0.03 270);
--color-tcb12-mut: #555c6a;
--color-tcb12-mut: oklch(0.47 0.02 265);
--color-tcb12-acc: #4a5fd6;
--color-tcb12-acc: oklch(0.55 0.17 268);
--font-tcb12-sans: 'Manrope', system-ui, sans-serif;
--shadow-tcb12-panel: 9px 9px 20px #c4c9d3, -9px -9px 20px #ffffff;
--shadow-tcb12-out: 4px 4px 8px #c4c9d3, -4px -4px 8px #ffffff;
--shadow-tcb12-in: inset 4px 4px 8px #c4c9d3, inset -4px -4px 8px #ffffff, 0 0 0 1px rgb(74 95 214 / 0.35);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tcb-12 {
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=Manrope: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=Manrope:wght@400;500;600;700;800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The raised/pressed
box-shadowpair became two@themeshadow tokens; the:checkedswap ispeer-checked:shadow-tcb12-in. --surfacebecame--color-tcb12-surface, sobg-tcb12-surfaceexists as a utility.- UI upgrade from the CSS original: the pressed state adds a faint accent edge and the label darkens to ink, so the state doesn't rely on soft shadows alone.
- UI upgrade: label copy moved from
#59606etooklch(0.47)(6:1 on the surface), checked labels to 11:1.
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: Neumorphism Checkbox in Tailwind CSS — Soft UI
Source: https://codefronts.com/components/tailwind-css-checkboxes/neumorphism-checkbox-tailwind-soft-ui/
Soft-UI boxes that look extruded when off and pressed-in when on: the two states are two shadow tokens, shadow-tcb12-out and peer-checked:shadow-tcb12-in. Checked labels darken and a thin accent edge keeps the state legible — neumorphism's usual weakness.
## HTML
```html
<section class="tcb-12 w-full min-h-svh grid place-items-center bg-tcb12-surface px-5 py-14 font-tcb12-sans text-tcb12-mut selection:bg-tcb12-acc selection:text-white" aria-label="Neumorphic checkboxes">
<div class="flex w-full max-w-[25rem] flex-col gap-1.5 rounded-[22px] bg-tcb12-surface p-5 shadow-tcb12-panel">
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only" checked><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Silent mode</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Haptic feedback</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Battery saver</span></label>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcb12-surface: #e6e9ef;
--color-tcb12-surface: oklch(0.93 0.008 265);
--color-tcb12-ink: #2b3040;
--color-tcb12-ink: oklch(0.3 0.03 270);
--color-tcb12-mut: #555c6a;
--color-tcb12-mut: oklch(0.47 0.02 265);
--color-tcb12-acc: #4a5fd6;
--color-tcb12-acc: oklch(0.55 0.17 268);
--font-tcb12-sans: 'Manrope', system-ui, sans-serif;
--shadow-tcb12-panel: 9px 9px 20px #c4c9d3, -9px -9px 20px #ffffff;
--shadow-tcb12-out: 4px 4px 8px #c4c9d3, -4px -4px 8px #ffffff;
--shadow-tcb12-in: inset 4px 4px 8px #c4c9d3, inset -4px -4px 8px #ffffff, 0 0 0 1px rgb(74 95 214 / 0.35);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tcb-12 {
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: Neumorphism Checkbox in Tailwind CSS — Soft UI
Source: https://codefronts.com/components/tailwind-css-checkboxes/neumorphism-checkbox-tailwind-soft-ui/
Soft-UI boxes that look extruded when off and pressed-in when on: the two states are two shadow tokens, shadow-tcb12-out and peer-checked:shadow-tcb12-in. Checked labels darken and a thin accent edge keeps the state legible — neumorphism's usual weakness.
## HTML
```html
<section class="tcb-12 w-full min-h-svh grid place-items-center bg-tcb12-surface px-5 py-14 font-tcb12-sans text-tcb12-mut selection:bg-tcb12-acc selection:text-white" aria-label="Neumorphic checkboxes">
<div class="flex w-full max-w-[25rem] flex-col gap-1.5 rounded-[22px] bg-tcb12-surface p-5 shadow-tcb12-panel">
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only" checked><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Silent mode</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Haptic feedback</span></label>
<label class="group flex min-h-14 cursor-pointer items-center gap-4 px-2.5"><input type="checkbox" class="peer sr-only"><span aria-hidden="true" class="grid size-[30px] flex-none place-items-center rounded-[9px] bg-tcb12-surface text-tcb12-acc shadow-tcb12-out transition-shadow duration-300 peer-checked:shadow-tcb12-in peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tcb12-acc motion-reduce:transition-none"><svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" class="size-4 scale-50 opacity-0 transition duration-250 ease-[cubic-bezier(.2,.9,.3,1.2)] group-has-checked:scale-100 group-has-checked:opacity-100"><path d="M20 6 9 17l-5-5"/></svg></span><span class="text-[15px] font-semibold transition-colors group-has-checked:text-tcb12-ink">Battery saver</span></label>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcb12-surface: #e6e9ef;
--color-tcb12-surface: oklch(0.93 0.008 265);
--color-tcb12-ink: #2b3040;
--color-tcb12-ink: oklch(0.3 0.03 270);
--color-tcb12-mut: #555c6a;
--color-tcb12-mut: oklch(0.47 0.02 265);
--color-tcb12-acc: #4a5fd6;
--color-tcb12-acc: oklch(0.55 0.17 268);
--font-tcb12-sans: 'Manrope', system-ui, sans-serif;
--shadow-tcb12-panel: 9px 9px 20px #c4c9d3, -9px -9px 20px #ffffff;
--shadow-tcb12-out: 4px 4px 8px #c4c9d3, -4px -4px 8px #ffffff;
--shadow-tcb12-in: inset 4px 4px 8px #c4c9d3, inset -4px -4px 8px #ffffff, 0 0 0 1px rgb(74 95 214 / 0.35);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tcb-12 {
width: 100%;
min-height: 100svh;
}
```How this works
Light and shade. Neumorphism pairs a dark shadow bottom-right with a white one top-left on a surface the same colour as the page. Swapping both for inset versions presses the element in.
Contrast rescue. Soft shadows alone fail WCAG non-text contrast. The checked state adds the accent tick, a darker label and a 1px accent ring, so state never depends on shadow alone.
Make it yours
- Surface: all four colours derive from
--color-tcb12-surface; keep the light shadow white. - Deeper press: raise the inset offsets to 6px.
- Round:
rounded-fullfor radio-style soft buttons. - Dark neumorphism: surface
#2b2f36, shadows#1f2227/#373c45.
Gotchas — read before shipping
- Pure neumorphism fails 3:1 non-text contrast — keep a colour cue.
- Shadow transitions repaint; fine for a handful of controls.
- The page background must match the surface exactly or the illusion breaks.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Box-shadow is universal.