17 / 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
Clay Icon Tiles and App Grid
Nine clay app tiles on a squircle grid, each hue generated from a single --h value, with a 3D perspective tilt on hover and a staggered load-in that uses only animation-delay derived from each tile's index. This is the pattern that sells claymorphism — playful, tactile, and cheap enough to render at 60 fps on a phone.
Untitled UI Pro: a 10,000+ component Figma UI kit · from $129 one-time
Untitled UI · Affiliate link
The code
<section class="cl-17" aria-label="Clay icon tiles and app grid demo">
<div class="cl-17__stage">
<header class="cl-17__head">
<h2 class="cl-17__h">Nine tiles, one hue variable</h2>
<p class="cl-17__lede">Hover to tilt. Fill and both shadow colours are derived from each tile's <code>--h</code>, so nothing needs per-colour tuning.</p>
</header>
<ul class="cl-17__grid">
<li class="cl-17__cell" style="--cl-17-h:28;--cl-17-i:0"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 11.2 12 4l8 7.2V20a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z" fill="currentColor"/></svg><span>Home</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:62;--cl-17-i:1"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3.5 14.6 9l6 .9-4.3 4.2 1 6-5.3-2.8-5.3 2.8 1-6L3.4 9.9 9.4 9z" fill="currentColor"/></svg><span>Streaks</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:145;--cl-17-i:2"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M5 4h9l5 5v11a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm8 1.8V10h4.2z" fill="currentColor"/></svg><span>Docs</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:190;--cl-17-i:3"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 5h16v11H4zm5 13h6v2H9z" fill="currentColor"/></svg><span>Watch</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:232;--cl-17-i:4"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18zm.9 4h-1.8v5.5l4.4 2.6.9-1.5-3.5-2z" fill="currentColor"/></svg><span>Focus</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:280;--cl-17-i:5"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 20.3 10.6 19C6 14.9 3.5 12.6 3.5 9.6A4.1 4.1 0 0 1 7.6 5.5c1.5 0 2.9.7 3.8 1.9.9-1.2 2.3-1.9 3.8-1.9a4.1 4.1 0 0 1 4.1 4.1c0 3-2.5 5.3-7.1 9.4z" fill="currentColor"/></svg><span>Saved</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:318;--cl-17-i:6"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm0 2c-4 0-7 2.2-7 5v1h14v-1c0-2.8-3-5-7-5z" fill="currentColor"/></svg><span>People</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:352;--cl-17-i:7"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 3h2l.4 2.3 2 .8 1.9-1.3 1.4 1.4-1.3 1.9.8 2L20.7 11v2l-2.3.4-.8 2 1.3 1.9-1.4 1.4-1.9-1.3-2 .8L13 20.7h-2l-.4-2.3-2-.8-1.9 1.3-1.4-1.4 1.3-1.9-.8-2L3.3 13v-2l2.3-.4.8-2L5.1 6.7l1.4-1.4 1.9 1.3 2-.8zM12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" fill="currentColor"/></svg><span>Settings</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:12;--cl-17-i:8"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 4h2v7h7v2h-7v7h-2v-7H4v-2h7z" fill="currentColor"/></svg><span>Add</span></button></li>
</ul>
<p class="cl-17__chip" aria-hidden="true">oklch hue rotation · individual transform properties · animation-delay: calc(--i * 60ms)</p>
</div>
</section><section class="cl-17" aria-label="Clay icon tiles and app grid demo">
<div class="cl-17__stage">
<header class="cl-17__head">
<h2 class="cl-17__h">Nine tiles, one hue variable</h2>
<p class="cl-17__lede">Hover to tilt. Fill and both shadow colours are derived from each tile's <code>--h</code>, so nothing needs per-colour tuning.</p>
</header>
<ul class="cl-17__grid">
<li class="cl-17__cell" style="--cl-17-h:28;--cl-17-i:0"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 11.2 12 4l8 7.2V20a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z" fill="currentColor"/></svg><span>Home</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:62;--cl-17-i:1"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3.5 14.6 9l6 .9-4.3 4.2 1 6-5.3-2.8-5.3 2.8 1-6L3.4 9.9 9.4 9z" fill="currentColor"/></svg><span>Streaks</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:145;--cl-17-i:2"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M5 4h9l5 5v11a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm8 1.8V10h4.2z" fill="currentColor"/></svg><span>Docs</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:190;--cl-17-i:3"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 5h16v11H4zm5 13h6v2H9z" fill="currentColor"/></svg><span>Watch</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:232;--cl-17-i:4"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18zm.9 4h-1.8v5.5l4.4 2.6.9-1.5-3.5-2z" fill="currentColor"/></svg><span>Focus</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:280;--cl-17-i:5"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 20.3 10.6 19C6 14.9 3.5 12.6 3.5 9.6A4.1 4.1 0 0 1 7.6 5.5c1.5 0 2.9.7 3.8 1.9.9-1.2 2.3-1.9 3.8-1.9a4.1 4.1 0 0 1 4.1 4.1c0 3-2.5 5.3-7.1 9.4z" fill="currentColor"/></svg><span>Saved</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:318;--cl-17-i:6"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm0 2c-4 0-7 2.2-7 5v1h14v-1c0-2.8-3-5-7-5z" fill="currentColor"/></svg><span>People</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:352;--cl-17-i:7"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 3h2l.4 2.3 2 .8 1.9-1.3 1.4 1.4-1.3 1.9.8 2L20.7 11v2l-2.3.4-.8 2 1.3 1.9-1.4 1.4-1.9-1.3-2 .8L13 20.7h-2l-.4-2.3-2-.8-1.9 1.3-1.4-1.4 1.3-1.9-.8-2L3.3 13v-2l2.3-.4.8-2L5.1 6.7l1.4-1.4 1.9 1.3 2-.8zM12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" fill="currentColor"/></svg><span>Settings</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:12;--cl-17-i:8"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 4h2v7h7v2h-7v7h-2v-7H4v-2h7z" fill="currentColor"/></svg><span>Add</span></button></li>
</ul>
<p class="cl-17__chip" aria-hidden="true">oklch hue rotation · individual transform properties · animation-delay: calc(--i * 60ms)</p>
</div>
</section>.cl-17,
.cl-17 *,
.cl-17 *::before,
.cl-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-17 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-17-bg);
--cl-17-bg: oklch(0.94 0.02 250);
--cl-17-ink: oklch(0.27 0.04 250);
--cl-17-mut: oklch(0.5 0.03 250);
--cl-17-shade: oklch(0.55 0.06 250/.4);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-17-ink);
}
.cl-17__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(22px,4vw,36px);
padding: clamp(20px,5vw,56px);
background: radial-gradient(85% 60% at 50% 0%,oklch(0.98 0.02 250),transparent 70%);
}
.cl-17__head {
text-align: center;
max-width: 56ch;
display: grid;
gap: 9px;
}
.cl-17__h {
font-size: clamp(23px,3.8vw,34px);
font-weight: 780;
letter-spacing: -.022em;
text-wrap: balance;
}
.cl-17__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-17-mut);
text-wrap: pretty;
}
.cl-17__lede code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 13.5px;
}
.cl-17__grid {
list-style: none;
display: grid;
grid-template-columns: repeat(3,minmax(88px,132px));
gap: clamp(14px,2.6vw,24px);
perspective: 900px;
padding: 6px;
}
.cl-17__cell {
display: grid;
}
.cl-17__tile {
--cl-17-h: 30;
display: grid;
place-items: center;
align-content: center;
gap: 9px;
aspect-ratio: 1;
padding: 10px;
border: 0;
border-radius: 34px;
font: inherit;
cursor: pointer;
color: oklch(0.28 0.08 var(--cl-17-h));
background: oklch(0.85 0.1 var(--cl-17-h));
transform-style: preserve-3d;
box-shadow: 0 18px 30px -10px oklch(0.52 0.13 var(--cl-17-h)/.5),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 15px 20px -7px oklch(1 0.02 var(--cl-17-h)/.95);
animation: cl-17-pop .55s cubic-bezier(.34,1.5,.5,1) backwards;
animation-delay: calc(var(--cl-17-i) * 60ms);
transition: rotate .35s cubic-bezier(.2,.8,.3,1.1),translate .4s cubic-bezier(.34,1.35,.5,1),scale .4s cubic-bezier(.34,1.35,.5,1),box-shadow .4s;
}
@keyframes cl-17-pop {
from {
opacity: 0;
scale: .7;
translate: 0 16px;
}
to {
opacity: 1;
scale: 1;
translate: 0 0;
}
}
.cl-17__tile:hover {
rotate: x 13deg;
translate: 0 -7px;
scale: 1.05;
box-shadow: 0 30px 44px -12px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 17px 22px -7px oklch(1 0.02 var(--cl-17-h)/.98);
}
.cl-17__tile:active {
rotate: x 0deg;
translate: 0 2px;
scale: .95;
box-shadow: inset 0 14px 22px -8px oklch(0.52 0.13 var(--cl-17-h)/.6),inset 0 -10px 18px -10px oklch(1 0.02 var(--cl-17-h)/.8);
}
.cl-17__tile:focus-visible {
outline: 3px solid oklch(0.32 0.09 var(--cl-17-h));
outline-offset: 4px;
}
.cl-17__tile span {
font-size: 12px;
font-weight: 680;
letter-spacing: -.005em;
}
@supports (corner-shape: squircle) {
.cl-17__tile {
border-radius: 36%;
corner-shape: squircle;
}
}
.cl-17__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-17-mut);
padding: 9px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.6);
box-shadow: inset 0 -4px 10px -8px var(--cl-17-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-17__tile {
animation: none;
}
.cl-17 * {
transition-duration: .01ms !important;
}
}.cl-17,
.cl-17 *,
.cl-17 *::before,
.cl-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-17 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-17-bg);
--cl-17-bg: oklch(0.94 0.02 250);
--cl-17-ink: oklch(0.27 0.04 250);
--cl-17-mut: oklch(0.5 0.03 250);
--cl-17-shade: oklch(0.55 0.06 250/.4);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-17-ink);
}
.cl-17__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(22px,4vw,36px);
padding: clamp(20px,5vw,56px);
background: radial-gradient(85% 60% at 50% 0%,oklch(0.98 0.02 250),transparent 70%);
}
.cl-17__head {
text-align: center;
max-width: 56ch;
display: grid;
gap: 9px;
}
.cl-17__h {
font-size: clamp(23px,3.8vw,34px);
font-weight: 780;
letter-spacing: -.022em;
text-wrap: balance;
}
.cl-17__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-17-mut);
text-wrap: pretty;
}
.cl-17__lede code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 13.5px;
}
.cl-17__grid {
list-style: none;
display: grid;
grid-template-columns: repeat(3,minmax(88px,132px));
gap: clamp(14px,2.6vw,24px);
perspective: 900px;
padding: 6px;
}
.cl-17__cell {
display: grid;
}
.cl-17__tile {
--cl-17-h: 30;
display: grid;
place-items: center;
align-content: center;
gap: 9px;
aspect-ratio: 1;
padding: 10px;
border: 0;
border-radius: 34px;
font: inherit;
cursor: pointer;
color: oklch(0.28 0.08 var(--cl-17-h));
background: oklch(0.85 0.1 var(--cl-17-h));
transform-style: preserve-3d;
box-shadow: 0 18px 30px -10px oklch(0.52 0.13 var(--cl-17-h)/.5),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 15px 20px -7px oklch(1 0.02 var(--cl-17-h)/.95);
animation: cl-17-pop .55s cubic-bezier(.34,1.5,.5,1) backwards;
animation-delay: calc(var(--cl-17-i) * 60ms);
transition: rotate .35s cubic-bezier(.2,.8,.3,1.1),translate .4s cubic-bezier(.34,1.35,.5,1),scale .4s cubic-bezier(.34,1.35,.5,1),box-shadow .4s;
}
@keyframes cl-17-pop {
from {
opacity: 0;
scale: .7;
translate: 0 16px;
}
to {
opacity: 1;
scale: 1;
translate: 0 0;
}
}
.cl-17__tile:hover {
rotate: x 13deg;
translate: 0 -7px;
scale: 1.05;
box-shadow: 0 30px 44px -12px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 17px 22px -7px oklch(1 0.02 var(--cl-17-h)/.98);
}
.cl-17__tile:active {
rotate: x 0deg;
translate: 0 2px;
scale: .95;
box-shadow: inset 0 14px 22px -8px oklch(0.52 0.13 var(--cl-17-h)/.6),inset 0 -10px 18px -10px oklch(1 0.02 var(--cl-17-h)/.8);
}
.cl-17__tile:focus-visible {
outline: 3px solid oklch(0.32 0.09 var(--cl-17-h));
outline-offset: 4px;
}
.cl-17__tile span {
font-size: 12px;
font-weight: 680;
letter-spacing: -.005em;
}
@supports (corner-shape: squircle) {
.cl-17__tile {
border-radius: 36%;
corner-shape: squircle;
}
}
.cl-17__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-17-mut);
padding: 9px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.6);
box-shadow: inset 0 -4px 10px -8px var(--cl-17-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-17__tile {
animation: none;
}
.cl-17 * {
transition-duration: .01ms !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: Clay Icon Tiles and App Grid
Source: https://codefronts.com/design-styles/css-claymorphism/clay-icon-tiles-and-app-grid/
Nine clay app tiles on a squircle grid, each hue generated from a single --h value, with a 3D perspective tilt on hover and a staggered load-in that uses only animation-delay derived from each tile's index. This is the pattern that sells claymorphism — playful, tactile, and cheap enough to render at 60 fps on a phone.
## HTML
```html
<section class="cl-17" aria-label="Clay icon tiles and app grid demo">
<div class="cl-17__stage">
<header class="cl-17__head">
<h2 class="cl-17__h">Nine tiles, one hue variable</h2>
<p class="cl-17__lede">Hover to tilt. Fill and both shadow colours are derived from each tile's <code>--h</code>, so nothing needs per-colour tuning.</p>
</header>
<ul class="cl-17__grid">
<li class="cl-17__cell" style="--cl-17-h:28;--cl-17-i:0"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 11.2 12 4l8 7.2V20a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z" fill="currentColor"/></svg><span>Home</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:62;--cl-17-i:1"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3.5 14.6 9l6 .9-4.3 4.2 1 6-5.3-2.8-5.3 2.8 1-6L3.4 9.9 9.4 9z" fill="currentColor"/></svg><span>Streaks</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:145;--cl-17-i:2"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M5 4h9l5 5v11a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm8 1.8V10h4.2z" fill="currentColor"/></svg><span>Docs</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:190;--cl-17-i:3"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 5h16v11H4zm5 13h6v2H9z" fill="currentColor"/></svg><span>Watch</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:232;--cl-17-i:4"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18zm.9 4h-1.8v5.5l4.4 2.6.9-1.5-3.5-2z" fill="currentColor"/></svg><span>Focus</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:280;--cl-17-i:5"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 20.3 10.6 19C6 14.9 3.5 12.6 3.5 9.6A4.1 4.1 0 0 1 7.6 5.5c1.5 0 2.9.7 3.8 1.9.9-1.2 2.3-1.9 3.8-1.9a4.1 4.1 0 0 1 4.1 4.1c0 3-2.5 5.3-7.1 9.4z" fill="currentColor"/></svg><span>Saved</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:318;--cl-17-i:6"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm0 2c-4 0-7 2.2-7 5v1h14v-1c0-2.8-3-5-7-5z" fill="currentColor"/></svg><span>People</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:352;--cl-17-i:7"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 3h2l.4 2.3 2 .8 1.9-1.3 1.4 1.4-1.3 1.9.8 2L20.7 11v2l-2.3.4-.8 2 1.3 1.9-1.4 1.4-1.9-1.3-2 .8L13 20.7h-2l-.4-2.3-2-.8-1.9 1.3-1.4-1.4 1.3-1.9-.8-2L3.3 13v-2l2.3-.4.8-2L5.1 6.7l1.4-1.4 1.9 1.3 2-.8zM12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" fill="currentColor"/></svg><span>Settings</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:12;--cl-17-i:8"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 4h2v7h7v2h-7v7h-2v-7H4v-2h7z" fill="currentColor"/></svg><span>Add</span></button></li>
</ul>
<p class="cl-17__chip" aria-hidden="true">oklch hue rotation · individual transform properties · animation-delay: calc(--i * 60ms)</p>
</div>
</section>
```
## CSS
```css
.cl-17,
.cl-17 *,
.cl-17 *::before,
.cl-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-17 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-17-bg);
--cl-17-bg: oklch(0.94 0.02 250);
--cl-17-ink: oklch(0.27 0.04 250);
--cl-17-mut: oklch(0.5 0.03 250);
--cl-17-shade: oklch(0.55 0.06 250/.4);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-17-ink);
}
.cl-17__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(22px,4vw,36px);
padding: clamp(20px,5vw,56px);
background: radial-gradient(85% 60% at 50% 0%,oklch(0.98 0.02 250),transparent 70%);
}
.cl-17__head {
text-align: center;
max-width: 56ch;
display: grid;
gap: 9px;
}
.cl-17__h {
font-size: clamp(23px,3.8vw,34px);
font-weight: 780;
letter-spacing: -.022em;
text-wrap: balance;
}
.cl-17__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-17-mut);
text-wrap: pretty;
}
.cl-17__lede code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 13.5px;
}
.cl-17__grid {
list-style: none;
display: grid;
grid-template-columns: repeat(3,minmax(88px,132px));
gap: clamp(14px,2.6vw,24px);
perspective: 900px;
padding: 6px;
}
.cl-17__cell {
display: grid;
}
.cl-17__tile {
--cl-17-h: 30;
display: grid;
place-items: center;
align-content: center;
gap: 9px;
aspect-ratio: 1;
padding: 10px;
border: 0;
border-radius: 34px;
font: inherit;
cursor: pointer;
color: oklch(0.28 0.08 var(--cl-17-h));
background: oklch(0.85 0.1 var(--cl-17-h));
transform-style: preserve-3d;
box-shadow: 0 18px 30px -10px oklch(0.52 0.13 var(--cl-17-h)/.5),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 15px 20px -7px oklch(1 0.02 var(--cl-17-h)/.95);
animation: cl-17-pop .55s cubic-bezier(.34,1.5,.5,1) backwards;
animation-delay: calc(var(--cl-17-i) * 60ms);
transition: rotate .35s cubic-bezier(.2,.8,.3,1.1),translate .4s cubic-bezier(.34,1.35,.5,1),scale .4s cubic-bezier(.34,1.35,.5,1),box-shadow .4s;
}
@keyframes cl-17-pop {
from {
opacity: 0;
scale: .7;
translate: 0 16px;
}
to {
opacity: 1;
scale: 1;
translate: 0 0;
}
}
.cl-17__tile:hover {
rotate: x 13deg;
translate: 0 -7px;
scale: 1.05;
box-shadow: 0 30px 44px -12px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 17px 22px -7px oklch(1 0.02 var(--cl-17-h)/.98);
}
.cl-17__tile:active {
rotate: x 0deg;
translate: 0 2px;
scale: .95;
box-shadow: inset 0 14px 22px -8px oklch(0.52 0.13 var(--cl-17-h)/.6),inset 0 -10px 18px -10px oklch(1 0.02 var(--cl-17-h)/.8);
}
.cl-17__tile:focus-visible {
outline: 3px solid oklch(0.32 0.09 var(--cl-17-h));
outline-offset: 4px;
}
.cl-17__tile span {
font-size: 12px;
font-weight: 680;
letter-spacing: -.005em;
}
@supports (corner-shape: squircle) {
.cl-17__tile {
border-radius: 36%;
corner-shape: squircle;
}
}
.cl-17__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-17-mut);
padding: 9px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.6);
box-shadow: inset 0 -4px 10px -8px var(--cl-17-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-17__tile {
animation: none;
}
.cl-17 * {
transition-duration: .01ms !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: Clay Icon Tiles and App Grid
Source: https://codefronts.com/design-styles/css-claymorphism/clay-icon-tiles-and-app-grid/
Nine clay app tiles on a squircle grid, each hue generated from a single --h value, with a 3D perspective tilt on hover and a staggered load-in that uses only animation-delay derived from each tile's index. This is the pattern that sells claymorphism — playful, tactile, and cheap enough to render at 60 fps on a phone.
## HTML
```html
<section class="cl-17" aria-label="Clay icon tiles and app grid demo">
<div class="cl-17__stage">
<header class="cl-17__head">
<h2 class="cl-17__h">Nine tiles, one hue variable</h2>
<p class="cl-17__lede">Hover to tilt. Fill and both shadow colours are derived from each tile's <code>--h</code>, so nothing needs per-colour tuning.</p>
</header>
<ul class="cl-17__grid">
<li class="cl-17__cell" style="--cl-17-h:28;--cl-17-i:0"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 11.2 12 4l8 7.2V20a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z" fill="currentColor"/></svg><span>Home</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:62;--cl-17-i:1"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3.5 14.6 9l6 .9-4.3 4.2 1 6-5.3-2.8-5.3 2.8 1-6L3.4 9.9 9.4 9z" fill="currentColor"/></svg><span>Streaks</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:145;--cl-17-i:2"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M5 4h9l5 5v11a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm8 1.8V10h4.2z" fill="currentColor"/></svg><span>Docs</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:190;--cl-17-i:3"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M4 5h16v11H4zm5 13h6v2H9z" fill="currentColor"/></svg><span>Watch</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:232;--cl-17-i:4"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 3a9 9 0 1 1 0 18 9 9 0 0 1 0-18zm.9 4h-1.8v5.5l4.4 2.6.9-1.5-3.5-2z" fill="currentColor"/></svg><span>Focus</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:280;--cl-17-i:5"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 20.3 10.6 19C6 14.9 3.5 12.6 3.5 9.6A4.1 4.1 0 0 1 7.6 5.5c1.5 0 2.9.7 3.8 1.9.9-1.2 2.3-1.9 3.8-1.9a4.1 4.1 0 0 1 4.1 4.1c0 3-2.5 5.3-7.1 9.4z" fill="currentColor"/></svg><span>Saved</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:318;--cl-17-i:6"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm0 2c-4 0-7 2.2-7 5v1h14v-1c0-2.8-3-5-7-5z" fill="currentColor"/></svg><span>People</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:352;--cl-17-i:7"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 3h2l.4 2.3 2 .8 1.9-1.3 1.4 1.4-1.3 1.9.8 2L20.7 11v2l-2.3.4-.8 2 1.3 1.9-1.4 1.4-1.9-1.3-2 .8L13 20.7h-2l-.4-2.3-2-.8-1.9 1.3-1.4-1.4 1.3-1.9-.8-2L3.3 13v-2l2.3-.4.8-2L5.1 6.7l1.4-1.4 1.9 1.3 2-.8zM12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" fill="currentColor"/></svg><span>Settings</span></button></li>
<li class="cl-17__cell" style="--cl-17-h:12;--cl-17-i:8"><button class="cl-17__tile" type="button"><svg viewBox="0 0 24 24" width="30" height="30" aria-hidden="true"><path d="M11 4h2v7h7v2h-7v7h-2v-7H4v-2h7z" fill="currentColor"/></svg><span>Add</span></button></li>
</ul>
<p class="cl-17__chip" aria-hidden="true">oklch hue rotation · individual transform properties · animation-delay: calc(--i * 60ms)</p>
</div>
</section>
```
## CSS
```css
.cl-17,
.cl-17 *,
.cl-17 *::before,
.cl-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cl-17 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--cl-17-bg);
--cl-17-bg: oklch(0.94 0.02 250);
--cl-17-ink: oklch(0.27 0.04 250);
--cl-17-mut: oklch(0.5 0.03 250);
--cl-17-shade: oklch(0.55 0.06 250/.4);
font-family: system-ui,-apple-system,'Segoe UI',sans-serif;
color: var(--cl-17-ink);
}
.cl-17__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: clamp(22px,4vw,36px);
padding: clamp(20px,5vw,56px);
background: radial-gradient(85% 60% at 50% 0%,oklch(0.98 0.02 250),transparent 70%);
}
.cl-17__head {
text-align: center;
max-width: 56ch;
display: grid;
gap: 9px;
}
.cl-17__h {
font-size: clamp(23px,3.8vw,34px);
font-weight: 780;
letter-spacing: -.022em;
text-wrap: balance;
}
.cl-17__lede {
font-size: 15px;
line-height: 1.6;
color: var(--cl-17-mut);
text-wrap: pretty;
}
.cl-17__lede code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 13.5px;
}
.cl-17__grid {
list-style: none;
display: grid;
grid-template-columns: repeat(3,minmax(88px,132px));
gap: clamp(14px,2.6vw,24px);
perspective: 900px;
padding: 6px;
}
.cl-17__cell {
display: grid;
}
.cl-17__tile {
--cl-17-h: 30;
display: grid;
place-items: center;
align-content: center;
gap: 9px;
aspect-ratio: 1;
padding: 10px;
border: 0;
border-radius: 34px;
font: inherit;
cursor: pointer;
color: oklch(0.28 0.08 var(--cl-17-h));
background: oklch(0.85 0.1 var(--cl-17-h));
transform-style: preserve-3d;
box-shadow: 0 18px 30px -10px oklch(0.52 0.13 var(--cl-17-h)/.5),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 15px 20px -7px oklch(1 0.02 var(--cl-17-h)/.95);
animation: cl-17-pop .55s cubic-bezier(.34,1.5,.5,1) backwards;
animation-delay: calc(var(--cl-17-i) * 60ms);
transition: rotate .35s cubic-bezier(.2,.8,.3,1.1),translate .4s cubic-bezier(.34,1.35,.5,1),scale .4s cubic-bezier(.34,1.35,.5,1),box-shadow .4s;
}
@keyframes cl-17-pop {
from {
opacity: 0;
scale: .7;
translate: 0 16px;
}
to {
opacity: 1;
scale: 1;
translate: 0 0;
}
}
.cl-17__tile:hover {
rotate: x 13deg;
translate: 0 -7px;
scale: 1.05;
box-shadow: 0 30px 44px -12px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 -13px 20px -9px oklch(0.52 0.13 var(--cl-17-h)/.55),inset 0 17px 22px -7px oklch(1 0.02 var(--cl-17-h)/.98);
}
.cl-17__tile:active {
rotate: x 0deg;
translate: 0 2px;
scale: .95;
box-shadow: inset 0 14px 22px -8px oklch(0.52 0.13 var(--cl-17-h)/.6),inset 0 -10px 18px -10px oklch(1 0.02 var(--cl-17-h)/.8);
}
.cl-17__tile:focus-visible {
outline: 3px solid oklch(0.32 0.09 var(--cl-17-h));
outline-offset: 4px;
}
.cl-17__tile span {
font-size: 12px;
font-weight: 680;
letter-spacing: -.005em;
}
@supports (corner-shape: squircle) {
.cl-17__tile {
border-radius: 36%;
corner-shape: squircle;
}
}
.cl-17__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: var(--cl-17-mut);
padding: 9px 16px;
border-radius: 99px;
text-align: center;
background: oklch(1 0 0/.6);
box-shadow: inset 0 -4px 10px -8px var(--cl-17-shade),inset 0 6px 10px -6px oklch(1 0 0);
}
@media (prefers-reduced-motion: reduce) {
.cl-17__tile {
animation: none;
}
.cl-17 * {
transition-duration: .01ms !important;
}
}
```How this works
Every tile shares one rule; only a hue changes. That is the whole colour system:
.tile{ --h:30;
background: oklch(0.84 0.11 var(--h));
box-shadow: 0 18px 30px -10px oklch(0.52 0.13 var(--h)/.5),
inset 0 -13px 20px -9px oklch(0.52 0.13 var(--h)/.55),
inset 0 15px 20px -7px oklch(1 0.02 var(--h)/.95);
}Because both shadow colours are derived from the same hue, every tile stays internally consistent — no per-colour shadow tuning, which is what usually makes multi-colour clay grids look muddy.
The hover tilt is real 3D, one transform, GPU only:
.tile{ transform-style:preserve-3d }
.tile:hover{ rotate: x 12deg; translate:0 -6px; scale:1.05 }Using the individual rotate/translate/scale properties instead of a single transform means each can carry its own easing and duration — the tilt can settle faster than the lift.
The staggered reveal uses an inline --i per tile:
.tile{ animation: pop .5s backwards cubic-bezier(.34,1.5,.5,1); animation-delay: calc(var(--i) * 60ms) }backwards fill is essential — it holds the tile at its pre-animation state during the delay, so nothing flashes at full size before its turn.
Make it yours
- Notification dots: reuse demo 12's count bubble; keep it outside the tile's overflow so the clay corners stay intact.
- Folder tile: a 2x2 mini-grid of 40%-scale glyphs inside one tile, with the parent's radius divided by 2 for the children.
- Press feedback:
:active{scale:.94; rotate:x 0deg}— the tile flattens back as it is pushed in, which reads as pressure. - Bigger grid: swap to
grid-template-columns:repeat(auto-fit,minmax(96px,1fr))and the stagger still works because the delay is index-based, not position-based.
Gotchas — read before shipping
- perspective must live on the grid (the parent), not on each tile, or every tile gets its own vanishing point and the row looks warped.
- Rotating a tile on X clips its own drop shadow against the grid's overflow — keep the container unclipped or add padding.
- Staggered delays over ~600 ms total feel slow on repeat visits. Cap the stagger at 9-12 items, or run it once with a session flag.
- Hue-only theming breaks contrast if lightness varies: keep L and C fixed across tiles (0.84 / 0.11 here) and only rotate H.
- Emoji glyphs inside clay tiles render with their own colours and shadows and fight the material. Use monochrome inline SVG that inherits currentColor.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by oklch(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 104+.
Individual transform properties: Chrome 104 / Safari 14.1 / Firefox 72. corner-shape squircle (Chrome 139+) is applied inside @supports as a progressive enhancement; everything else is universal.