Skip to content
← writing

A neumorphic toggle from two inset shadows

css
neumorphism
box-shadow
toggle

I came across a five-step Sketch recipe for one of those soft, pillowy toggles and wanted to see how little CSS it'd take to make a real, working one. Turns out: not much. The whole soft look is a gradient and two inset shadows.

Two shadows pointing opposite ways

Start with a pill (border-radius big enough to round the ends) and a left-to-right gradient, light on one side, dark on the other:

background: linear-gradient(90deg, #4b4b4b, #111111);

Then the trick. Add two inset shadows that point in opposite directions, one dark and one light:

box-shadow:
  inset 20px 0 30px -10px #171717,   /* dark, pressing in from the left  */
  inset -20px 0 30px -10px #494949;  /* light, pressing in from the right */

That's the entire neumorphic effect. The opposing soft shadows make the surface look like it was pressed out of one piece of material, not drawn with a border and a fill. No outline anywhere, and it still reads as a distinct, sunken shape.

Give it a thumb that moves

The static recipe stops there. A toggle needs to do something, so I added a raised knob that slides between the two halves:

.neu-toggle__thumb {
  width: calc(50% - 6px);
  border-radius: 100px;
  background: linear-gradient(180deg, #3c3c3c, #1b1b1b);
  box-shadow: 0 2px 6px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.1);
  transition: transform .28s cubic-bezier(.2,.7,.2,1);
}
.neu-toggle[data-index="1"] .neu-toggle__thumb { transform: translateX(100%); }

The knob gets its own drop shadow and a one-pixel top highlight so it reads as raised against the sunken track. A data-index on the wrapper drives the slide, and a springy ease keeps it from feeling sluggish. The icons sit on top, so the one over the thumb is bright and the other dims back.

Under the hood it's a real radiogroup with two radio buttons, so it's keyboard- and screen-reader-friendly, and the motion sits behind prefers-reduced-motion. The look is the fun part, but a toggle nobody can operate isn't worth shipping.

Grab the component (sun/moon or your own two options) on the Neumorphic Toggle page.

Ask your agent to implement this

Read the full writeup at https://seangeng.com/writing/a-neumorphic-toggle.md and implement it in my project.

It covers: A neumorphic toggle from two inset shadows — Recreating a soft, pressed-in segmented toggle from a Sketch recipe: a gradient pill, two opposing inset shadows for the depth, and a raised thumb that slides between sun and moon. Pure CSS.

Requirements:
- Follow the technique/approach exactly as described in the writeup.
- Adapt names, colors, and styling to my project's existing conventions.
- If it's a component, make it reusable with sensible props and TypeScript types.
- Keep it accessible: semantic HTML, keyboard support, and respect prefers-reduced-motion.
- When done, tell me which files you created or changed and how to use it.

Paste into Claude Code, Codex, Cursor, or any agent. view raw .md