01 / 20
All 20 in 20 CSS Claymorphism
- 01Claymorphism Shadow Recipe Reference Build
- 02Inner Highlight and Inner Shadow Layering
- 03Border Radius Scale for Puffy Shapes
- 04Claymorphism vs Neumorphism Side by Side
- 05Claymorphism with Glassmorphism Hybrid
- 06Light Source Consistency Across a Clay Layout
- 07Clay Depth Tiers for Visual Hierarchy
- 08Tailwind CSS Claymorphism Implementation
- 09Clay Button Press and Squish States
- 10Clay Toggle Switch and Checkbox Set
- 11Clay Input Field and Search Bar
- 12Clay Badge & Pill Tag System
- 13Claymorphism Card Component
- 14Clay Modal Dialog with Floating Depth
- 15Clay Pricing Table with Raised Popular Tier
- 16Clay Bottom Tab Bar for Mobile
- 17Clay Icon Tiles and App Grid
- 18Clay Toast & Floating Alert Bubbles
- 19Clay Dark Mode Shadow Recalibration
- 20Clay Animation Performance & Transform Optimization
Claymorphism Shadow Recipe Reference Build
The reference build for the whole trend: one clay object, four radio steps, and the shadow assembled one layer at a time — flat fill, outer drop, inset far-side shadow, inset lit-side highlight. The code panel lights up line by line as you step, so the formula is learned rather than copied. All three layers are always present and only their colors change, so every step animates.
Untitled UI Pro: a 10,000+ component Figma UI kit · from $129 one-time
Untitled UI · Affiliate link
The code
<section class="cl-01" aria-label="Claymorphism shadow recipe reference build">
<div class="cl-01__stage">
<header class="cl-01__head">
<p class="cl-01__eyebrow">Recipe reference</p>
<h2 class="cl-01__h">Clay is three shadow layers</h2>
<p class="cl-01__lede">Step through the build. One outer drop for mass, one inset shade for thickness, one inset highlight for the sheen.</p>
</header>
<div class="cl-01__lab">
<fieldset class="cl-01__steps">
<legend class="cl-01__legend">Shadow layers</legend>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s1">
<label class="cl-01__step" for="cl-01-s1"><b>1</b> Flat fill</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s2">
<label class="cl-01__step" for="cl-01-s2"><b>2</b> + outer drop</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s3">
<label class="cl-01__step" for="cl-01-s3"><b>3</b> + inset shade</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s4" checked>
<label class="cl-01__step" for="cl-01-s4"><b>4</b> + inset highlight</label>
</fieldset>
<div class="cl-01__object">
<div class="cl-01__clay">
<span class="cl-01__glyph" aria-hidden="true"></span>
<p class="cl-01__caption">clay</p>
</div>
</div>
<pre class="cl-01__code"><code><span class="cl-01__ln cl-01__ln--0">.clay {
border-radius: 44px;
background: var(--clay);</span>
<span class="cl-01__ln cl-01__ln--1"> box-shadow:
0 22px 40px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--2">
inset 0 -16px 26px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--3">
inset 0 18px 26px -8px var(--light)</span><span class="cl-01__ln cl-01__ln--0">;
}</span></code></pre>
</div>
<p class="cl-01__chip" aria-hidden="true">3-layer formula · :has() stepper · fixed layer count = animatable box-shadow</p>
</div>
</section><section class="cl-01" aria-label="Claymorphism shadow recipe reference build">
<div class="cl-01__stage">
<header class="cl-01__head">
<p class="cl-01__eyebrow">Recipe reference</p>
<h2 class="cl-01__h">Clay is three shadow layers</h2>
<p class="cl-01__lede">Step through the build. One outer drop for mass, one inset shade for thickness, one inset highlight for the sheen.</p>
</header>
<div class="cl-01__lab">
<fieldset class="cl-01__steps">
<legend class="cl-01__legend">Shadow layers</legend>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s1">
<label class="cl-01__step" for="cl-01-s1"><b>1</b> Flat fill</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s2">
<label class="cl-01__step" for="cl-01-s2"><b>2</b> + outer drop</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s3">
<label class="cl-01__step" for="cl-01-s3"><b>3</b> + inset shade</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s4" checked>
<label class="cl-01__step" for="cl-01-s4"><b>4</b> + inset highlight</label>
</fieldset>
<div class="cl-01__object">
<div class="cl-01__clay">
<span class="cl-01__glyph" aria-hidden="true"></span>
<p class="cl-01__caption">clay</p>
</div>
</div>
<pre class="cl-01__code"><code><span class="cl-01__ln cl-01__ln--0">.clay {
border-radius: 44px;
background: var(--clay);</span>
<span class="cl-01__ln cl-01__ln--1"> box-shadow:
0 22px 40px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--2">
inset 0 -16px 26px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--3">
inset 0 18px 26px -8px var(--light)</span><span class="cl-01__ln cl-01__ln--0">;
}</span></code></pre>
</div>
<p class="cl-01__chip" aria-hidden="true">3-layer formula · :has() stepper · fixed layer count = animatable box-shadow</p>
</div>
</section>.cl-01,
.cl-01 *,
.cl-01 *::before,
.cl-01 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-01-bg);
--cl-01-bg: oklch(0.94 0.028 60);
--cl-01-clay: oklch(0.83 0.11 32);
--cl-01-shade: color-mix(in oklch,var(--cl-01-clay) 55%,oklch(0.42 0.12 30));
--cl-01-light: oklch(0.99 0.03 85/.9);
--cl-01-ink: oklch(0.31 0.05 40);
--cl-01-mut: oklch(0.53 0.04 45);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-01-ink);
}
.cl-01__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(24px,4vw,40px);
padding: clamp(22px,5vw,60px);
background: radial-gradient(90% 70% at 20% 0%,oklch(0.97 0.04 70),transparent 65%);
}
.cl-01__head {
max-width: 58ch;
text-align: center;
display: grid;
gap: 8px;
}
.cl-01__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--cl-01-mut);
}
.cl-01__h {
font-size: clamp(24px,4vw,36px);
font-weight: 780;
letter-spacing: -.02em;
text-wrap: balance;
}
.cl-01__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-01-mut);
text-wrap: pretty;
}
.cl-01__lab {
display: grid;
gap: clamp(20px,3vw,34px);
grid-template-columns: 1fr;
justify-items: center;
width: min(100%,940px);
}
@media (min-width: 900px) {
.cl-01__lab {
grid-template-columns: auto auto 1fr;
align-items: center;
}
}
.cl-01__steps {
border: 0;
display: grid;
gap: 10px;
min-width: 190px;
}
.cl-01__legend {
font-size: 11.5px;
font-weight: 700;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--cl-01-mut);
padding-bottom: 8px;
}
.cl-01__r {
position: absolute;
width: 1px;
height: 1px;
opacity: 0;
clip-path: inset(50%);
}
.cl-01__step {
display: flex;
align-items: center;
gap: 11px;
min-height: 46px;
padding: 0 18px;
border-radius: 20px;
font-size: 14.5px;
font-weight: 600;
cursor: pointer;
color: var(--cl-01-mut);
background: color-mix(in oklch,var(--cl-01-bg) 88%,white);
box-shadow: 0 8px 16px -8px var(--cl-01-shade),inset 0 -6px 12px -8px var(--cl-01-shade),inset 0 8px 12px -6px var(--cl-01-light);
transition: color .3s,translate .3s cubic-bezier(.34,1.4,.5,1),box-shadow .3s;
}
.cl-01__step b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 50%;
font-size: 12px;
background: color-mix(in oklch,var(--cl-01-clay) 40%,white);
color: var(--cl-01-ink);
}
.cl-01__step:hover {
translate: 2px 0;
}
.cl-01__r:checked+.cl-01__step {
color: var(--cl-01-ink);
background: var(--cl-01-clay);
translate: 6px 0;
box-shadow: 0 14px 24px -10px var(--cl-01-shade),inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 16px -6px var(--cl-01-light);
}
.cl-01__r:checked+.cl-01__step b {
background: oklch(1 0 0/.75);
}
.cl-01__r:focus-visible+.cl-01__step {
outline: 3px solid var(--cl-01-ink);
outline-offset: 3px;
}
.cl-01__object {
display: grid;
place-items: center;
padding: 14px;
}
.cl-01__clay {
display: grid;
place-items: center;
align-content: center;
gap: 10px;
width: clamp(180px,26vw,224px);
aspect-ratio: 1;
border-radius: 44px;
background: var(--cl-01-clay);
box-shadow: 0 22px 40px -10px var(--cl-01-c1,transparent),inset 0 -16px 26px -10px var(--cl-01-c2,transparent),inset 0 18px 26px -8px var(--cl-01-c3,transparent);
transition: box-shadow .55s cubic-bezier(.4,0,.2,1),translate .55s cubic-bezier(.34,1.3,.5,1);
}
.cl-01__glyph {
width: 64px;
height: 64px;
border-radius: 26px;
background: color-mix(in oklch,var(--cl-01-clay) 60%,white);
box-shadow: inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 14px -6px var(--cl-01-light);
}
.cl-01__caption {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .22em;
text-transform: uppercase;
color: color-mix(in oklch,var(--cl-01-ink) 75%,var(--cl-01-clay));
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
translate: 0 -4px;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
translate: 0 -6px;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
--cl-01-c3: var(--cl-01-light);
translate: 0 -8px;
}
.cl-01__code {
width: min(100%,420px);
margin: 0;
padding: 22px 24px;
border-radius: 28px;
background: color-mix(in oklch,var(--cl-01-bg) 82%,white);
box-shadow: inset 0 -10px 20px -12px var(--cl-01-shade),inset 0 12px 20px -10px var(--cl-01-light),0 16px 30px -14px var(--cl-01-shade);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12.5px;
line-height: 1.85;
overflow-x: auto;
color: var(--cl-01-ink);
}
.cl-01__ln {
opacity: .24;
transition: opacity .45s;
}
.cl-01__ln--0 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--1 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--2,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--2 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--3 {
opacity: 1;
}
.cl-01__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-01-mut);
padding: 8px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.5);
box-shadow: inset 0 -4px 10px -8px var(--cl-01-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-01 * {
transition-duration: .01ms !important;
animation: none !important;
}
}.cl-01,
.cl-01 *,
.cl-01 *::before,
.cl-01 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-01-bg);
--cl-01-bg: oklch(0.94 0.028 60);
--cl-01-clay: oklch(0.83 0.11 32);
--cl-01-shade: color-mix(in oklch,var(--cl-01-clay) 55%,oklch(0.42 0.12 30));
--cl-01-light: oklch(0.99 0.03 85/.9);
--cl-01-ink: oklch(0.31 0.05 40);
--cl-01-mut: oklch(0.53 0.04 45);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-01-ink);
}
.cl-01__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(24px,4vw,40px);
padding: clamp(22px,5vw,60px);
background: radial-gradient(90% 70% at 20% 0%,oklch(0.97 0.04 70),transparent 65%);
}
.cl-01__head {
max-width: 58ch;
text-align: center;
display: grid;
gap: 8px;
}
.cl-01__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--cl-01-mut);
}
.cl-01__h {
font-size: clamp(24px,4vw,36px);
font-weight: 780;
letter-spacing: -.02em;
text-wrap: balance;
}
.cl-01__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-01-mut);
text-wrap: pretty;
}
.cl-01__lab {
display: grid;
gap: clamp(20px,3vw,34px);
grid-template-columns: 1fr;
justify-items: center;
width: min(100%,940px);
}
@media (min-width: 900px) {
.cl-01__lab {
grid-template-columns: auto auto 1fr;
align-items: center;
}
}
.cl-01__steps {
border: 0;
display: grid;
gap: 10px;
min-width: 190px;
}
.cl-01__legend {
font-size: 11.5px;
font-weight: 700;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--cl-01-mut);
padding-bottom: 8px;
}
.cl-01__r {
position: absolute;
width: 1px;
height: 1px;
opacity: 0;
clip-path: inset(50%);
}
.cl-01__step {
display: flex;
align-items: center;
gap: 11px;
min-height: 46px;
padding: 0 18px;
border-radius: 20px;
font-size: 14.5px;
font-weight: 600;
cursor: pointer;
color: var(--cl-01-mut);
background: color-mix(in oklch,var(--cl-01-bg) 88%,white);
box-shadow: 0 8px 16px -8px var(--cl-01-shade),inset 0 -6px 12px -8px var(--cl-01-shade),inset 0 8px 12px -6px var(--cl-01-light);
transition: color .3s,translate .3s cubic-bezier(.34,1.4,.5,1),box-shadow .3s;
}
.cl-01__step b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 50%;
font-size: 12px;
background: color-mix(in oklch,var(--cl-01-clay) 40%,white);
color: var(--cl-01-ink);
}
.cl-01__step:hover {
translate: 2px 0;
}
.cl-01__r:checked+.cl-01__step {
color: var(--cl-01-ink);
background: var(--cl-01-clay);
translate: 6px 0;
box-shadow: 0 14px 24px -10px var(--cl-01-shade),inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 16px -6px var(--cl-01-light);
}
.cl-01__r:checked+.cl-01__step b {
background: oklch(1 0 0/.75);
}
.cl-01__r:focus-visible+.cl-01__step {
outline: 3px solid var(--cl-01-ink);
outline-offset: 3px;
}
.cl-01__object {
display: grid;
place-items: center;
padding: 14px;
}
.cl-01__clay {
display: grid;
place-items: center;
align-content: center;
gap: 10px;
width: clamp(180px,26vw,224px);
aspect-ratio: 1;
border-radius: 44px;
background: var(--cl-01-clay);
box-shadow: 0 22px 40px -10px var(--cl-01-c1,transparent),inset 0 -16px 26px -10px var(--cl-01-c2,transparent),inset 0 18px 26px -8px var(--cl-01-c3,transparent);
transition: box-shadow .55s cubic-bezier(.4,0,.2,1),translate .55s cubic-bezier(.34,1.3,.5,1);
}
.cl-01__glyph {
width: 64px;
height: 64px;
border-radius: 26px;
background: color-mix(in oklch,var(--cl-01-clay) 60%,white);
box-shadow: inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 14px -6px var(--cl-01-light);
}
.cl-01__caption {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .22em;
text-transform: uppercase;
color: color-mix(in oklch,var(--cl-01-ink) 75%,var(--cl-01-clay));
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
translate: 0 -4px;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
translate: 0 -6px;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
--cl-01-c3: var(--cl-01-light);
translate: 0 -8px;
}
.cl-01__code {
width: min(100%,420px);
margin: 0;
padding: 22px 24px;
border-radius: 28px;
background: color-mix(in oklch,var(--cl-01-bg) 82%,white);
box-shadow: inset 0 -10px 20px -12px var(--cl-01-shade),inset 0 12px 20px -10px var(--cl-01-light),0 16px 30px -14px var(--cl-01-shade);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12.5px;
line-height: 1.85;
overflow-x: auto;
color: var(--cl-01-ink);
}
.cl-01__ln {
opacity: .24;
transition: opacity .45s;
}
.cl-01__ln--0 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--1 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--2,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--2 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--3 {
opacity: 1;
}
.cl-01__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-01-mut);
padding: 8px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.5);
box-shadow: inset 0 -4px 10px -8px var(--cl-01-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-01 * {
transition-duration: .01ms !important;
animation: none !important;
}
}Here's a working CSS Claymorphism 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: Claymorphism Shadow Recipe Reference Build
Source: https://codefronts.com/design-styles/css-claymorphism/claymorphism-shadow-recipe-reference-build/
The reference build for the whole trend: one clay object, four radio steps, and the shadow assembled one layer at a time — flat fill, outer drop, inset far-side shadow, inset lit-side highlight. The code panel lights up line by line as you step, so the formula is learned rather than copied. All three layers are always present and only their colors change, so every step animates.
## HTML
```html
<section class="cl-01" aria-label="Claymorphism shadow recipe reference build">
<div class="cl-01__stage">
<header class="cl-01__head">
<p class="cl-01__eyebrow">Recipe reference</p>
<h2 class="cl-01__h">Clay is three shadow layers</h2>
<p class="cl-01__lede">Step through the build. One outer drop for mass, one inset shade for thickness, one inset highlight for the sheen.</p>
</header>
<div class="cl-01__lab">
<fieldset class="cl-01__steps">
<legend class="cl-01__legend">Shadow layers</legend>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s1">
<label class="cl-01__step" for="cl-01-s1"><b>1</b> Flat fill</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s2">
<label class="cl-01__step" for="cl-01-s2"><b>2</b> + outer drop</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s3">
<label class="cl-01__step" for="cl-01-s3"><b>3</b> + inset shade</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s4" checked>
<label class="cl-01__step" for="cl-01-s4"><b>4</b> + inset highlight</label>
</fieldset>
<div class="cl-01__object">
<div class="cl-01__clay">
<span class="cl-01__glyph" aria-hidden="true"></span>
<p class="cl-01__caption">clay</p>
</div>
</div>
<pre class="cl-01__code"><code><span class="cl-01__ln cl-01__ln--0">.clay {
border-radius: 44px;
background: var(--clay);</span>
<span class="cl-01__ln cl-01__ln--1"> box-shadow:
0 22px 40px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--2">
inset 0 -16px 26px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--3">
inset 0 18px 26px -8px var(--light)</span><span class="cl-01__ln cl-01__ln--0">;
}</span></code></pre>
</div>
<p class="cl-01__chip" aria-hidden="true">3-layer formula · :has() stepper · fixed layer count = animatable box-shadow</p>
</div>
</section>
```
## CSS
```css
.cl-01,
.cl-01 *,
.cl-01 *::before,
.cl-01 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-01-bg);
--cl-01-bg: oklch(0.94 0.028 60);
--cl-01-clay: oklch(0.83 0.11 32);
--cl-01-shade: color-mix(in oklch,var(--cl-01-clay) 55%,oklch(0.42 0.12 30));
--cl-01-light: oklch(0.99 0.03 85/.9);
--cl-01-ink: oklch(0.31 0.05 40);
--cl-01-mut: oklch(0.53 0.04 45);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-01-ink);
}
.cl-01__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(24px,4vw,40px);
padding: clamp(22px,5vw,60px);
background: radial-gradient(90% 70% at 20% 0%,oklch(0.97 0.04 70),transparent 65%);
}
.cl-01__head {
max-width: 58ch;
text-align: center;
display: grid;
gap: 8px;
}
.cl-01__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--cl-01-mut);
}
.cl-01__h {
font-size: clamp(24px,4vw,36px);
font-weight: 780;
letter-spacing: -.02em;
text-wrap: balance;
}
.cl-01__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-01-mut);
text-wrap: pretty;
}
.cl-01__lab {
display: grid;
gap: clamp(20px,3vw,34px);
grid-template-columns: 1fr;
justify-items: center;
width: min(100%,940px);
}
@media (min-width: 900px) {
.cl-01__lab {
grid-template-columns: auto auto 1fr;
align-items: center;
}
}
.cl-01__steps {
border: 0;
display: grid;
gap: 10px;
min-width: 190px;
}
.cl-01__legend {
font-size: 11.5px;
font-weight: 700;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--cl-01-mut);
padding-bottom: 8px;
}
.cl-01__r {
position: absolute;
width: 1px;
height: 1px;
opacity: 0;
clip-path: inset(50%);
}
.cl-01__step {
display: flex;
align-items: center;
gap: 11px;
min-height: 46px;
padding: 0 18px;
border-radius: 20px;
font-size: 14.5px;
font-weight: 600;
cursor: pointer;
color: var(--cl-01-mut);
background: color-mix(in oklch,var(--cl-01-bg) 88%,white);
box-shadow: 0 8px 16px -8px var(--cl-01-shade),inset 0 -6px 12px -8px var(--cl-01-shade),inset 0 8px 12px -6px var(--cl-01-light);
transition: color .3s,translate .3s cubic-bezier(.34,1.4,.5,1),box-shadow .3s;
}
.cl-01__step b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 50%;
font-size: 12px;
background: color-mix(in oklch,var(--cl-01-clay) 40%,white);
color: var(--cl-01-ink);
}
.cl-01__step:hover {
translate: 2px 0;
}
.cl-01__r:checked+.cl-01__step {
color: var(--cl-01-ink);
background: var(--cl-01-clay);
translate: 6px 0;
box-shadow: 0 14px 24px -10px var(--cl-01-shade),inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 16px -6px var(--cl-01-light);
}
.cl-01__r:checked+.cl-01__step b {
background: oklch(1 0 0/.75);
}
.cl-01__r:focus-visible+.cl-01__step {
outline: 3px solid var(--cl-01-ink);
outline-offset: 3px;
}
.cl-01__object {
display: grid;
place-items: center;
padding: 14px;
}
.cl-01__clay {
display: grid;
place-items: center;
align-content: center;
gap: 10px;
width: clamp(180px,26vw,224px);
aspect-ratio: 1;
border-radius: 44px;
background: var(--cl-01-clay);
box-shadow: 0 22px 40px -10px var(--cl-01-c1,transparent),inset 0 -16px 26px -10px var(--cl-01-c2,transparent),inset 0 18px 26px -8px var(--cl-01-c3,transparent);
transition: box-shadow .55s cubic-bezier(.4,0,.2,1),translate .55s cubic-bezier(.34,1.3,.5,1);
}
.cl-01__glyph {
width: 64px;
height: 64px;
border-radius: 26px;
background: color-mix(in oklch,var(--cl-01-clay) 60%,white);
box-shadow: inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 14px -6px var(--cl-01-light);
}
.cl-01__caption {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .22em;
text-transform: uppercase;
color: color-mix(in oklch,var(--cl-01-ink) 75%,var(--cl-01-clay));
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
translate: 0 -4px;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
translate: 0 -6px;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
--cl-01-c3: var(--cl-01-light);
translate: 0 -8px;
}
.cl-01__code {
width: min(100%,420px);
margin: 0;
padding: 22px 24px;
border-radius: 28px;
background: color-mix(in oklch,var(--cl-01-bg) 82%,white);
box-shadow: inset 0 -10px 20px -12px var(--cl-01-shade),inset 0 12px 20px -10px var(--cl-01-light),0 16px 30px -14px var(--cl-01-shade);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12.5px;
line-height: 1.85;
overflow-x: auto;
color: var(--cl-01-ink);
}
.cl-01__ln {
opacity: .24;
transition: opacity .45s;
}
.cl-01__ln--0 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--1 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--2,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--2 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--3 {
opacity: 1;
}
.cl-01__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-01-mut);
padding: 8px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.5);
box-shadow: inset 0 -4px 10px -8px var(--cl-01-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-01 * {
transition-duration: .01ms !important;
animation: none !important;
}
}
```Here's a working CSS Claymorphism 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: Claymorphism Shadow Recipe Reference Build
Source: https://codefronts.com/design-styles/css-claymorphism/claymorphism-shadow-recipe-reference-build/
The reference build for the whole trend: one clay object, four radio steps, and the shadow assembled one layer at a time — flat fill, outer drop, inset far-side shadow, inset lit-side highlight. The code panel lights up line by line as you step, so the formula is learned rather than copied. All three layers are always present and only their colors change, so every step animates.
## HTML
```html
<section class="cl-01" aria-label="Claymorphism shadow recipe reference build">
<div class="cl-01__stage">
<header class="cl-01__head">
<p class="cl-01__eyebrow">Recipe reference</p>
<h2 class="cl-01__h">Clay is three shadow layers</h2>
<p class="cl-01__lede">Step through the build. One outer drop for mass, one inset shade for thickness, one inset highlight for the sheen.</p>
</header>
<div class="cl-01__lab">
<fieldset class="cl-01__steps">
<legend class="cl-01__legend">Shadow layers</legend>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s1">
<label class="cl-01__step" for="cl-01-s1"><b>1</b> Flat fill</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s2">
<label class="cl-01__step" for="cl-01-s2"><b>2</b> + outer drop</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s3">
<label class="cl-01__step" for="cl-01-s3"><b>3</b> + inset shade</label>
<input class="cl-01__r" type="radio" name="cl-01-step" id="cl-01-s4" checked>
<label class="cl-01__step" for="cl-01-s4"><b>4</b> + inset highlight</label>
</fieldset>
<div class="cl-01__object">
<div class="cl-01__clay">
<span class="cl-01__glyph" aria-hidden="true"></span>
<p class="cl-01__caption">clay</p>
</div>
</div>
<pre class="cl-01__code"><code><span class="cl-01__ln cl-01__ln--0">.clay {
border-radius: 44px;
background: var(--clay);</span>
<span class="cl-01__ln cl-01__ln--1"> box-shadow:
0 22px 40px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--2">
inset 0 -16px 26px -10px var(--shade),</span><span class="cl-01__ln cl-01__ln--3">
inset 0 18px 26px -8px var(--light)</span><span class="cl-01__ln cl-01__ln--0">;
}</span></code></pre>
</div>
<p class="cl-01__chip" aria-hidden="true">3-layer formula · :has() stepper · fixed layer count = animatable box-shadow</p>
</div>
</section>
```
## CSS
```css
.cl-01,
.cl-01 *,
.cl-01 *::before,
.cl-01 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-01-bg);
--cl-01-bg: oklch(0.94 0.028 60);
--cl-01-clay: oklch(0.83 0.11 32);
--cl-01-shade: color-mix(in oklch,var(--cl-01-clay) 55%,oklch(0.42 0.12 30));
--cl-01-light: oklch(0.99 0.03 85/.9);
--cl-01-ink: oklch(0.31 0.05 40);
--cl-01-mut: oklch(0.53 0.04 45);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-01-ink);
}
.cl-01__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(24px,4vw,40px);
padding: clamp(22px,5vw,60px);
background: radial-gradient(90% 70% at 20% 0%,oklch(0.97 0.04 70),transparent 65%);
}
.cl-01__head {
max-width: 58ch;
text-align: center;
display: grid;
gap: 8px;
}
.cl-01__eyebrow {
font-size: 12px;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--cl-01-mut);
}
.cl-01__h {
font-size: clamp(24px,4vw,36px);
font-weight: 780;
letter-spacing: -.02em;
text-wrap: balance;
}
.cl-01__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-01-mut);
text-wrap: pretty;
}
.cl-01__lab {
display: grid;
gap: clamp(20px,3vw,34px);
grid-template-columns: 1fr;
justify-items: center;
width: min(100%,940px);
}
@media (min-width: 900px) {
.cl-01__lab {
grid-template-columns: auto auto 1fr;
align-items: center;
}
}
.cl-01__steps {
border: 0;
display: grid;
gap: 10px;
min-width: 190px;
}
.cl-01__legend {
font-size: 11.5px;
font-weight: 700;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--cl-01-mut);
padding-bottom: 8px;
}
.cl-01__r {
position: absolute;
width: 1px;
height: 1px;
opacity: 0;
clip-path: inset(50%);
}
.cl-01__step {
display: flex;
align-items: center;
gap: 11px;
min-height: 46px;
padding: 0 18px;
border-radius: 20px;
font-size: 14.5px;
font-weight: 600;
cursor: pointer;
color: var(--cl-01-mut);
background: color-mix(in oklch,var(--cl-01-bg) 88%,white);
box-shadow: 0 8px 16px -8px var(--cl-01-shade),inset 0 -6px 12px -8px var(--cl-01-shade),inset 0 8px 12px -6px var(--cl-01-light);
transition: color .3s,translate .3s cubic-bezier(.34,1.4,.5,1),box-shadow .3s;
}
.cl-01__step b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 50%;
font-size: 12px;
background: color-mix(in oklch,var(--cl-01-clay) 40%,white);
color: var(--cl-01-ink);
}
.cl-01__step:hover {
translate: 2px 0;
}
.cl-01__r:checked+.cl-01__step {
color: var(--cl-01-ink);
background: var(--cl-01-clay);
translate: 6px 0;
box-shadow: 0 14px 24px -10px var(--cl-01-shade),inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 16px -6px var(--cl-01-light);
}
.cl-01__r:checked+.cl-01__step b {
background: oklch(1 0 0/.75);
}
.cl-01__r:focus-visible+.cl-01__step {
outline: 3px solid var(--cl-01-ink);
outline-offset: 3px;
}
.cl-01__object {
display: grid;
place-items: center;
padding: 14px;
}
.cl-01__clay {
display: grid;
place-items: center;
align-content: center;
gap: 10px;
width: clamp(180px,26vw,224px);
aspect-ratio: 1;
border-radius: 44px;
background: var(--cl-01-clay);
box-shadow: 0 22px 40px -10px var(--cl-01-c1,transparent),inset 0 -16px 26px -10px var(--cl-01-c2,transparent),inset 0 18px 26px -8px var(--cl-01-c3,transparent);
transition: box-shadow .55s cubic-bezier(.4,0,.2,1),translate .55s cubic-bezier(.34,1.3,.5,1);
}
.cl-01__glyph {
width: 64px;
height: 64px;
border-radius: 26px;
background: color-mix(in oklch,var(--cl-01-clay) 60%,white);
box-shadow: inset 0 -8px 14px -8px var(--cl-01-shade),inset 0 10px 14px -6px var(--cl-01-light);
}
.cl-01__caption {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .22em;
text-transform: uppercase;
color: color-mix(in oklch,var(--cl-01-ink) 75%,var(--cl-01-clay));
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
translate: 0 -4px;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
translate: 0 -6px;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__clay {
--cl-01-c1: var(--cl-01-shade);
--cl-01-c2: var(--cl-01-shade);
--cl-01-c3: var(--cl-01-light);
translate: 0 -8px;
}
.cl-01__code {
width: min(100%,420px);
margin: 0;
padding: 22px 24px;
border-radius: 28px;
background: color-mix(in oklch,var(--cl-01-bg) 82%,white);
box-shadow: inset 0 -10px 20px -12px var(--cl-01-shade),inset 0 12px 20px -10px var(--cl-01-light),0 16px 30px -14px var(--cl-01-shade);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12.5px;
line-height: 1.85;
overflow-x: auto;
color: var(--cl-01-ink);
}
.cl-01__ln {
opacity: .24;
transition: opacity .45s;
}
.cl-01__ln--0 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s2:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--1,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--1 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s3:checked) .cl-01__ln--2,
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--2 {
opacity: 1;
}
.cl-01__lab:has(#cl-01-s4:checked) .cl-01__ln--3 {
opacity: 1;
}
.cl-01__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-01-mut);
padding: 8px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.5);
box-shadow: inset 0 -4px 10px -8px var(--cl-01-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-01 * {
transition-duration: .01ms !important;
animation: none !important;
}
}
```How this works
Claymorphism is not a blur value, it is a three-layer contract. Every clay object in this collection is this:
--drop: 0 22px 40px -10px var(--shade); /* 1. mass + contact */
--shade-in: inset 0 -16px 26px -10px var(--shade); /* 2. far-side thickness */
--light-in: inset 0 18px 26px -8px var(--light); /* 3. lit-side sheen */
.clay{
border-radius:44px; /* puffy, never 8px */
background:var(--clay); /* lighter than the page */
box-shadow:var(--drop),var(--shade-in),var(--light-in);
}Layer 1 gives the object mass: a large, soft, slightly downward drop with a negative spread so it hugs the shape instead of haloing it. Layer 2 is the trick everyone misses — an inset shadow on the side away from the light makes the wall of the object look thick, which is what separates clay from a flat pastel rectangle. Layer 3 is the plasticine gloss: a wide, soft inset highlight on the lit side.
The stepper is pure CSS. Four radios sit in the lab, and :has() reads which one is checked:
.lab:has(#s3:checked) .clay{ --c1:var(--shade); --c2:var(--shade); --c3:transparent; }Why swap colors instead of adding layers? box-shadow only interpolates between lists with the same number of layers. Declare all three permanently and toggle each one's color between the real value and transparent, and the browser animates the build-up smoothly — the same technique demo 20 uses to get 60 fps depth changes.
Make it yours
- Re-hue the whole object in one line: change
--cl-01-clayand both shadow colors follow, because they arecolor-mix()derivations of it rather than hand-picked hex values. - Softer / harder clay: scale the blur radii together (
40px / 26px / 26px→28px / 18px / 18px) for a firmer, more matte material; raise them for marshmallow. - Deeper object: increase the inset shadow's negative offset (
-16px→-26px) and the object reads as a thicker slab. - Bake it into a token file: expose the three layers as
--clay-drop,--clay-inner-shade,--clay-inner-lightand every component in your app can compose them in onebox-shadowdeclaration.
Gotchas — read before shipping
- Layer count must match to animate:
box-shadowwith 1 layer → 3 layers snaps. Keep the list length fixed and animate the colors (or use@propertyregistered lengths). - Don't fill the object darker than the page — clay is lifted material. A fill darker than the background reads as a hole, which is inset neumorphism, not claymorphism (see demo 04).
- One light direction only. If the inset highlight is on top, the drop shadow must fall down and the inset shade must sit at the bottom. Mixed directions are the tell of hand-tuned, uncoordinated shadows.
- Big soft shadows are expensive to repaint. Never animate the blur or offset on hover — animate
transformand the shadow colors (demo 20 measures the difference). - Contrast still applies: pastel-on-pastel text fails WCAG 1.4.3 fast. Keep body copy at 4.5:1 against the clay fill, not against the page.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by :has(), oklch(), color-mix(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 105+.
:has() is the only modern requirement (Chrome 105 / Safari 15.4 / Firefox 121); layered inset box-shadow itself works in every engine since IE9. Replace oklch()/color-mix() with hex and the recipe runs anywhere.