18 / 51
All 51 in 51 CSS Buttons
- 01CSS Submit Button (Form Primary)
- 02CSS Primary and Secondary Button Pair
- 03CSS Ghost / Outline Button
- 04CSS Icon-Only Button with Accessible Tooltip
- 05CSS Gradient CTA Button
- 06CSS Loading Spinner Button (State Transition)
- 07CSS Disabled Button State (Full State Reference)
- 08CSS Button Group Component (Segmented Radio-Like)
- 09CSS Add to Cart Button
- 10CSS Download Progress Button
- 11CSS Like Heart Button
- 12CSS Confirm Delete Button
- 13CSS Play Pause Button
- 14CSS Subscribe Confetti Button
- 15CSS Magnetic Mercury Ripple Button
- 16CSS Brutalist Glitch Button
- 17CSS Neon Plasma Burst Button
- 18CSS Clay Press Button
- 19CSS Editorial Ink Spread Button
- 20CSS Particle Shard Burst Button
- 21CSS Brushed Brass Plate Button
- 22CSS Washi Paper Crane Button
- 23CSS Frosted Ice Cube Button
- 24CSS Vintage Typewriter Key Button
- 25CSS Lacquered Walnut Wood Button
- 26CSS Pharma Gel Capsule Button
- 27CSS Aged Copper Coin Button
- 28CSS Origami Fortune Cookie Button
- 29CSS Holographic Foil Sticker Button
- 30CSS Brutalist Concrete Slab Button
- 31CSS Mercury Bead Morph Button
- 32CSS Soft Pill Modern SaaS Button
- 33CSS Masking Tape Label Button
- 34CSS Obsidian Glass Shard Button
- 35CSS Wine Velvet Ribbon Button
- 36CSS LED Segment Display Button
- 37CSS Cassette Mixtape Label Button
- 38CSS Chalkboard Menu Button
- 39CSS Vinyl Record Sleeve Ripple Button
- 40CSS Polaroid Snapshot Button
- 41CSS Airline Boarding Pass Button
- 42CSS Aged Brass Subway Token Button
- 43CSS Vintage Rx Pharmacy Label Button
- 44CSS Bakelite Radio Dial Toggle Button
- 45CSS Regal Postage Stamp Button
- 46CSS Victorian Cigar Band Foil Button
- 47CSS Vintage Calculator Key Button
- 48CSS Toolbox Latch Spotlight Button
- 49CSS Receipt Paper Total Count-Up Button
- 50CSS IBM Punch Card Magnetic Follow Button
- 51CSS Brass Periscope Lens Button
CSS Clay Press Button
Fat, matte, extruded clay: two inner shadows carve the highlight and the shade, an outer shadow grounds it, and pressing squashes the shape on both axes so it deforms like real material instead of just moving down.
Build UI like this from scratch: Flexbox, Grid, animations & responsive CSS
ZTM · The CSS Bootcamp · 30‑day money-back guarantee · Affiliate link
The code
<div class="cb-18">
<div class="cb-18__stage">
<button class="cb-18__btn" type="button">
<span class="cb-18__ico" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
</span>
<span>Make something</span>
</button>
</div>
</div><div class="cb-18">
<div class="cb-18__stage">
<button class="cb-18__btn" type="button">
<span class="cb-18__ico" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
</span>
<span>Make something</span>
</button>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800&display=swap');
.cb-18 {
--bg: #e8ecf7;
--clay: #7c8cf8;
--deep: #2a3480;
--ink: #ffffff;
--chip: #fbbf24;
--radius: 1.5rem;
--spring: linear(0,.38 7%,.82 15%,1.08 23%,1.12 28%,1.05 37%,1 52%,1);
--sans: "Nunito",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(30rem 20rem at 50% 40%, #ffffff, transparent 70%), var(--bg);
font-family: var(--sans);
}
@supports (color: oklch(50% 0 0)) {
.cb-18 {
--bg: oklch(93.5% .02 265);
--clay: oklch(68% .16 275);
--deep: oklch(35% .14 275);
--chip: oklch(84% .16 82);
}
}
@media (prefers-color-scheme: dark) {
.cb-18:not([data-theme="light"]) {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
}
.cb-18[data-theme="dark"] {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
.cb-18,
.cb-18 *,
.cb-18 *::before,
.cb-18 *::after {
box-sizing: border-box;
}
.cb-18__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-18__btn {
cursor: pointer;
display: grid;
grid-auto-flow: column;
align-items: center;
gap: .7rem;
min-height: 4rem;
padding: 0 2rem 0 1.4rem;
border: 0;
border-radius: var(--radius);
font: inherit;
font-size: 1.0625rem;
font-weight: 800;
letter-spacing: -.01em;
color: var(--ink);
background: var(--clay);
box-shadow: inset 8px 8px 16px color-mix(in oklab,white 45%,transparent), inset -10px -10px 20px color-mix(in oklab,var(--deep) 42%,transparent), 0 18px 32px -16px color-mix(in oklab,var(--deep) 65%,transparent);
transition: translate .35s cubic-bezier(.16,1,.3,1), scale .35s cubic-bezier(.16,1,.3,1), box-shadow .3s ease;
-webkit-tap-highlight-color: transparent;
}
@supports (transition-timing-function: linear(0,1)) {
.cb-18__btn {
transition: translate .5s var(--spring), scale .5s var(--spring), box-shadow .3s ease;
}
}
.cb-18__ico {
display: grid;
place-items: center;
width: 2.1rem;
height: 2.1rem;
border-radius: 50%;
color: var(--deep);
background: var(--chip);
box-shadow: inset 3px 3px 6px color-mix(in oklab,white 55%,transparent), inset -3px -3px 6px color-mix(in oklab,var(--deep) 30%,transparent);
transition: rotate .5s cubic-bezier(.16,1,.3,1);
}
.cb-18__ico svg {
width: 1.05rem;
height: 1.05rem;
}
.cb-18__btn:hover {
translate: 0 -3px;
}
.cb-18__btn:hover .cb-18__ico {
rotate: 90deg;
}
.cb-18__btn:active {
scale: .96 .9;
translate: 0 2px;
box-shadow: inset 7px 7px 15px color-mix(in oklab,var(--deep) 38%,transparent), inset -7px -7px 14px color-mix(in oklab,white 32%,transparent), 0 6px 12px -10px color-mix(in oklab,var(--deep) 60%,transparent);
}
.cb-18__btn:focus-visible {
outline: 3px solid color-mix(in oklab,var(--deep) 60%,var(--clay));
outline-offset: 5px;
}
.cb-18__btn:disabled {
cursor: not-allowed;
filter: grayscale(.6);
opacity: .6;
}
@media (prefers-reduced-motion: reduce) {
.cb-18__btn,
.cb-18__ico {
transition: none;
}
}
@media (forced-colors: active) {
.cb-18__btn {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
box-shadow: none;
}
.cb-18__ico {
box-shadow: none;
border: 1px solid ButtonText;
}
}@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800&display=swap');
.cb-18 {
--bg: #e8ecf7;
--clay: #7c8cf8;
--deep: #2a3480;
--ink: #ffffff;
--chip: #fbbf24;
--radius: 1.5rem;
--spring: linear(0,.38 7%,.82 15%,1.08 23%,1.12 28%,1.05 37%,1 52%,1);
--sans: "Nunito",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(30rem 20rem at 50% 40%, #ffffff, transparent 70%), var(--bg);
font-family: var(--sans);
}
@supports (color: oklch(50% 0 0)) {
.cb-18 {
--bg: oklch(93.5% .02 265);
--clay: oklch(68% .16 275);
--deep: oklch(35% .14 275);
--chip: oklch(84% .16 82);
}
}
@media (prefers-color-scheme: dark) {
.cb-18:not([data-theme="light"]) {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
}
.cb-18[data-theme="dark"] {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
.cb-18,
.cb-18 *,
.cb-18 *::before,
.cb-18 *::after {
box-sizing: border-box;
}
.cb-18__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-18__btn {
cursor: pointer;
display: grid;
grid-auto-flow: column;
align-items: center;
gap: .7rem;
min-height: 4rem;
padding: 0 2rem 0 1.4rem;
border: 0;
border-radius: var(--radius);
font: inherit;
font-size: 1.0625rem;
font-weight: 800;
letter-spacing: -.01em;
color: var(--ink);
background: var(--clay);
box-shadow: inset 8px 8px 16px color-mix(in oklab,white 45%,transparent), inset -10px -10px 20px color-mix(in oklab,var(--deep) 42%,transparent), 0 18px 32px -16px color-mix(in oklab,var(--deep) 65%,transparent);
transition: translate .35s cubic-bezier(.16,1,.3,1), scale .35s cubic-bezier(.16,1,.3,1), box-shadow .3s ease;
-webkit-tap-highlight-color: transparent;
}
@supports (transition-timing-function: linear(0,1)) {
.cb-18__btn {
transition: translate .5s var(--spring), scale .5s var(--spring), box-shadow .3s ease;
}
}
.cb-18__ico {
display: grid;
place-items: center;
width: 2.1rem;
height: 2.1rem;
border-radius: 50%;
color: var(--deep);
background: var(--chip);
box-shadow: inset 3px 3px 6px color-mix(in oklab,white 55%,transparent), inset -3px -3px 6px color-mix(in oklab,var(--deep) 30%,transparent);
transition: rotate .5s cubic-bezier(.16,1,.3,1);
}
.cb-18__ico svg {
width: 1.05rem;
height: 1.05rem;
}
.cb-18__btn:hover {
translate: 0 -3px;
}
.cb-18__btn:hover .cb-18__ico {
rotate: 90deg;
}
.cb-18__btn:active {
scale: .96 .9;
translate: 0 2px;
box-shadow: inset 7px 7px 15px color-mix(in oklab,var(--deep) 38%,transparent), inset -7px -7px 14px color-mix(in oklab,white 32%,transparent), 0 6px 12px -10px color-mix(in oklab,var(--deep) 60%,transparent);
}
.cb-18__btn:focus-visible {
outline: 3px solid color-mix(in oklab,var(--deep) 60%,var(--clay));
outline-offset: 5px;
}
.cb-18__btn:disabled {
cursor: not-allowed;
filter: grayscale(.6);
opacity: .6;
}
@media (prefers-reduced-motion: reduce) {
.cb-18__btn,
.cb-18__ico {
transition: none;
}
}
@media (forced-colors: active) {
.cb-18__btn {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
box-shadow: none;
}
.cb-18__ico {
box-shadow: none;
border: 1px solid ButtonText;
}
}Here's a working CSS Button 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: CSS Clay Press Button
Source: https://codefronts.com/components/css-buttons/css-clay-press-button/
Fat, matte, extruded clay: two inner shadows carve the highlight and the shade, an outer shadow grounds it, and pressing squashes the shape on both axes so it deforms like real material instead of just moving down.
## HTML
```html
<div class="cb-18">
<div class="cb-18__stage">
<button class="cb-18__btn" type="button">
<span class="cb-18__ico" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
</span>
<span>Make something</span>
</button>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800&display=swap');
.cb-18 {
--bg: #e8ecf7;
--clay: #7c8cf8;
--deep: #2a3480;
--ink: #ffffff;
--chip: #fbbf24;
--radius: 1.5rem;
--spring: linear(0,.38 7%,.82 15%,1.08 23%,1.12 28%,1.05 37%,1 52%,1);
--sans: "Nunito",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(30rem 20rem at 50% 40%, #ffffff, transparent 70%), var(--bg);
font-family: var(--sans);
}
@supports (color: oklch(50% 0 0)) {
.cb-18 {
--bg: oklch(93.5% .02 265);
--clay: oklch(68% .16 275);
--deep: oklch(35% .14 275);
--chip: oklch(84% .16 82);
}
}
@media (prefers-color-scheme: dark) {
.cb-18:not([data-theme="light"]) {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
}
.cb-18[data-theme="dark"] {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
.cb-18,
.cb-18 *,
.cb-18 *::before,
.cb-18 *::after {
box-sizing: border-box;
}
.cb-18__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-18__btn {
cursor: pointer;
display: grid;
grid-auto-flow: column;
align-items: center;
gap: .7rem;
min-height: 4rem;
padding: 0 2rem 0 1.4rem;
border: 0;
border-radius: var(--radius);
font: inherit;
font-size: 1.0625rem;
font-weight: 800;
letter-spacing: -.01em;
color: var(--ink);
background: var(--clay);
box-shadow: inset 8px 8px 16px color-mix(in oklab,white 45%,transparent), inset -10px -10px 20px color-mix(in oklab,var(--deep) 42%,transparent), 0 18px 32px -16px color-mix(in oklab,var(--deep) 65%,transparent);
transition: translate .35s cubic-bezier(.16,1,.3,1), scale .35s cubic-bezier(.16,1,.3,1), box-shadow .3s ease;
-webkit-tap-highlight-color: transparent;
}
@supports (transition-timing-function: linear(0,1)) {
.cb-18__btn {
transition: translate .5s var(--spring), scale .5s var(--spring), box-shadow .3s ease;
}
}
.cb-18__ico {
display: grid;
place-items: center;
width: 2.1rem;
height: 2.1rem;
border-radius: 50%;
color: var(--deep);
background: var(--chip);
box-shadow: inset 3px 3px 6px color-mix(in oklab,white 55%,transparent), inset -3px -3px 6px color-mix(in oklab,var(--deep) 30%,transparent);
transition: rotate .5s cubic-bezier(.16,1,.3,1);
}
.cb-18__ico svg {
width: 1.05rem;
height: 1.05rem;
}
.cb-18__btn:hover {
translate: 0 -3px;
}
.cb-18__btn:hover .cb-18__ico {
rotate: 90deg;
}
.cb-18__btn:active {
scale: .96 .9;
translate: 0 2px;
box-shadow: inset 7px 7px 15px color-mix(in oklab,var(--deep) 38%,transparent), inset -7px -7px 14px color-mix(in oklab,white 32%,transparent), 0 6px 12px -10px color-mix(in oklab,var(--deep) 60%,transparent);
}
.cb-18__btn:focus-visible {
outline: 3px solid color-mix(in oklab,var(--deep) 60%,var(--clay));
outline-offset: 5px;
}
.cb-18__btn:disabled {
cursor: not-allowed;
filter: grayscale(.6);
opacity: .6;
}
@media (prefers-reduced-motion: reduce) {
.cb-18__btn,
.cb-18__ico {
transition: none;
}
}
@media (forced-colors: active) {
.cb-18__btn {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
box-shadow: none;
}
.cb-18__ico {
box-shadow: none;
border: 1px solid ButtonText;
}
}
```Here's a working CSS Button 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: CSS Clay Press Button
Source: https://codefronts.com/components/css-buttons/css-clay-press-button/
Fat, matte, extruded clay: two inner shadows carve the highlight and the shade, an outer shadow grounds it, and pressing squashes the shape on both axes so it deforms like real material instead of just moving down.
## HTML
```html
<div class="cb-18">
<div class="cb-18__stage">
<button class="cb-18__btn" type="button">
<span class="cb-18__ico" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
</span>
<span>Make something</span>
</button>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800&display=swap');
.cb-18 {
--bg: #e8ecf7;
--clay: #7c8cf8;
--deep: #2a3480;
--ink: #ffffff;
--chip: #fbbf24;
--radius: 1.5rem;
--spring: linear(0,.38 7%,.82 15%,1.08 23%,1.12 28%,1.05 37%,1 52%,1);
--sans: "Nunito",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(30rem 20rem at 50% 40%, #ffffff, transparent 70%), var(--bg);
font-family: var(--sans);
}
@supports (color: oklch(50% 0 0)) {
.cb-18 {
--bg: oklch(93.5% .02 265);
--clay: oklch(68% .16 275);
--deep: oklch(35% .14 275);
--chip: oklch(84% .16 82);
}
}
@media (prefers-color-scheme: dark) {
.cb-18:not([data-theme="light"]) {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
}
.cb-18[data-theme="dark"] {
--bg: #181b28;
--clay: #5b68d8;
--deep: #080a16;
}
.cb-18,
.cb-18 *,
.cb-18 *::before,
.cb-18 *::after {
box-sizing: border-box;
}
.cb-18__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-18__btn {
cursor: pointer;
display: grid;
grid-auto-flow: column;
align-items: center;
gap: .7rem;
min-height: 4rem;
padding: 0 2rem 0 1.4rem;
border: 0;
border-radius: var(--radius);
font: inherit;
font-size: 1.0625rem;
font-weight: 800;
letter-spacing: -.01em;
color: var(--ink);
background: var(--clay);
box-shadow: inset 8px 8px 16px color-mix(in oklab,white 45%,transparent), inset -10px -10px 20px color-mix(in oklab,var(--deep) 42%,transparent), 0 18px 32px -16px color-mix(in oklab,var(--deep) 65%,transparent);
transition: translate .35s cubic-bezier(.16,1,.3,1), scale .35s cubic-bezier(.16,1,.3,1), box-shadow .3s ease;
-webkit-tap-highlight-color: transparent;
}
@supports (transition-timing-function: linear(0,1)) {
.cb-18__btn {
transition: translate .5s var(--spring), scale .5s var(--spring), box-shadow .3s ease;
}
}
.cb-18__ico {
display: grid;
place-items: center;
width: 2.1rem;
height: 2.1rem;
border-radius: 50%;
color: var(--deep);
background: var(--chip);
box-shadow: inset 3px 3px 6px color-mix(in oklab,white 55%,transparent), inset -3px -3px 6px color-mix(in oklab,var(--deep) 30%,transparent);
transition: rotate .5s cubic-bezier(.16,1,.3,1);
}
.cb-18__ico svg {
width: 1.05rem;
height: 1.05rem;
}
.cb-18__btn:hover {
translate: 0 -3px;
}
.cb-18__btn:hover .cb-18__ico {
rotate: 90deg;
}
.cb-18__btn:active {
scale: .96 .9;
translate: 0 2px;
box-shadow: inset 7px 7px 15px color-mix(in oklab,var(--deep) 38%,transparent), inset -7px -7px 14px color-mix(in oklab,white 32%,transparent), 0 6px 12px -10px color-mix(in oklab,var(--deep) 60%,transparent);
}
.cb-18__btn:focus-visible {
outline: 3px solid color-mix(in oklab,var(--deep) 60%,var(--clay));
outline-offset: 5px;
}
.cb-18__btn:disabled {
cursor: not-allowed;
filter: grayscale(.6);
opacity: .6;
}
@media (prefers-reduced-motion: reduce) {
.cb-18__btn,
.cb-18__ico {
transition: none;
}
}
@media (forced-colors: active) {
.cb-18__btn {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
box-shadow: none;
}
.cb-18__ico {
box-shadow: none;
border: 1px solid ButtonText;
}
}
```How this works
Clay is entirely about the inset shadow pair — one light from the top-left, one dark from the bottom-right, both large and soft, plus a tight outer shadow for contact:
.cb-18__btn{
background:var(--clay);
box-shadow:
inset 8px 8px 16px color-mix(in oklab,white 55%,transparent),
inset -10px -10px 20px color-mix(in oklab,var(--deep) 45%,transparent),
0 16px 30px -14px color-mix(in oklab,var(--deep) 60%,transparent);
}The squash uses non-uniform scale — 0.96 across, 0.9 down — which is what sells deformation. Because scale is its own property now, it composes with the hover translate without either overwriting the other:
.cb-18__btn:hover{ translate:0 -3px; }
.cb-18__btn:active{ scale:.96 .9; translate:0 2px;
box-shadow:inset 6px 6px 14px color-mix(in oklab,var(--deep) 40%,transparent),
inset -6px -6px 12px color-mix(in oklab,white 35%,transparent); }Note the shadows swap direction on press: the light source now hits the far edge, which is exactly what happens when a soft surface dents. A springy linear() easing on release gives the material its rebound.
Make it yours
--clayis the only colour you need to change; the highlight and shade are mixed from it and--deep.- Radius is the personality:
2remis bubblegum,1remis app-like,50%makes a clay ball for icon buttons. - Increase both inset blurs together to inflate the button; unequal values make it look wet rather than matte.
- Add a second clay chip behind the label for a badge — the same shadow recipe scales down to 1rem elements.
- For dark clay, keep the highlight low (25-30% white) or it turns plastic.
Gotchas — read before shipping
- Clay is a low-contrast style by nature: the label must be a real ink colour, not a tint of the clay, or it fails contrast at every size.
- Large inset blurs are expensive at scale — do not put forty of these in a scrolling list with transitions on the shadows.
- Don't animate
border-radiusto fake the squash; scale is compositor-friendly and radius is not. - The classic mistake is one inset shadow. Two, in opposing directions, is the minimum for a rounded surface to read as volume.
- In forced-colors mode all of this disappears by design; make sure the button still has a border, or it vanishes entirely.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 113+ | 17.2+ | 112+ | 113+ |
linear() spring easing needs Chrome 113 / Safari 17.2 / Firefox 112, with a cubic-bezier fallback declared first. Individual scale/translate need Chrome 104 / Safari 14.1 / Firefox 72.