A soft UI checkbox that sits raised on its own surface and sinks in when checked, while the tick draws in your accent. The outset and inset shadows are listed in both states so they interpolate.
Also known as: soft ui checkbox, neumorphism checkbox css.
<label class="chk-neumorphic-checkbox">
<input type="checkbox">
<span class="chk-neumorphic-checkbox-box">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg>
</span>
Auto-save drafts
</label>.chk-neumorphic-checkbox {
--c: var(--chk-color, #3b82f6);
font-size: var(--chk-size, 24px);
position: relative;
display: inline-flex;
align-items: center;
gap: 0.6em;
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
line-height: 1.3;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
--surface: color-mix(in srgb, var(--c) 6%, #e4e8ee);
--shade: color-mix(in srgb, var(--c) 14%, #a3adbd);
gap: 0.8em;
padding: 0.9em 1.3em;
border-radius: 1em;
background: var(--surface);
color: color-mix(in srgb, var(--c) 20%, #4b5563);
font-weight: 500;}
.chk-neumorphic-checkbox input {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
margin: 0;
opacity: 0;
cursor: pointer;
z-index: 1;
}
.chk-neumorphic-checkbox-box {
display: grid;
place-items: center;
flex: none;
width: 1.5em;
height: 1.5em;
border-radius: 0.4em;
background: var(--surface);
box-shadow:
0.22em 0.22em 0.45em var(--shade),
-0.22em -0.22em 0.45em #fff,
inset 0 0 0 transparent,
inset 0 0 0 transparent;
transition: box-shadow 0.35s ease;
}
.chk-neumorphic-checkbox-box svg {
display: block;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
width: 0.95em;
height: 0.95em;
stroke: var(--c);
stroke-width: 3;
stroke-dasharray: 22;
stroke-dashoffset: 22;
filter: drop-shadow(0 0 0.1em color-mix(in srgb, var(--c) 45%, transparent));
transition: stroke-dashoffset 0.15s ease-in;
}
.chk-neumorphic-checkbox input:checked + .chk-neumorphic-checkbox-box {
box-shadow:
0 0 0 transparent,
0 0 0 transparent,
inset 0.15em 0.15em 0.3em var(--shade),
inset -0.15em -0.15em 0.3em #fff;
}
.chk-neumorphic-checkbox input:checked + .chk-neumorphic-checkbox-box svg {
stroke-dashoffset: 0;
transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1) 0.15s;
}
.chk-neumorphic-checkbox input:focus-visible + .chk-neumorphic-checkbox-box {
outline: 0.125em solid var(--c);
outline-offset: 0.18em;
}
@media (prefers-reduced-motion: reduce) {
.chk-neumorphic-checkbox, .chk-neumorphic-checkbox *, .chk-neumorphic-checkbox::before, .chk-neumorphic-checkbox::after, .chk-neumorphic-checkbox *::before, .chk-neumorphic-checkbox *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--chk-color on the element or a parent.
Currently previewing #3b82f6.--chk-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 24px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.