25 / 51
All 51 in 51 Tailwind CSS Buttons
- 01Tailwind Submit Button (Form Primary)
- 02Tailwind Primary and Secondary Button Pair
- 03Tailwind Ghost / Outline Button
- 04Tailwind Icon-Only Button with Accessible Tooltip
- 05Tailwind Gradient CTA Button
- 06Tailwind Loading Spinner Button (State Transition)
- 07Tailwind Disabled Button State (Full State Reference)
- 08Tailwind Button Group Component (Segmented Radio-Like)
- 09Tailwind Add to Cart Button
- 10Tailwind Download Progress Button
- 11Tailwind Like Heart Button
- 12Tailwind Confirm Delete Button
- 13Tailwind Play Pause Button
- 14Tailwind Subscribe Confetti Button
- 15Tailwind Magnetic Mercury Ripple Button
- 16Tailwind Brutalist Glitch Button
- 17Tailwind Neon Plasma Burst Button
- 18Tailwind Clay Press Button
- 19Tailwind Editorial Ink Spread Button
- 20Tailwind Particle Shard Burst Button
- 21Tailwind Brushed Brass Plate Button
- 22Tailwind Washi Paper Crane Button
- 23Tailwind Frosted Ice Cube Button
- 24Tailwind Vintage Typewriter Key Button
- 25Tailwind Lacquered Walnut Wood Button
- 26Tailwind Pharma Gel Capsule Button
- 27Tailwind Aged Copper Coin Button
- 28Tailwind Origami Fortune Cookie Button
- 29Tailwind Holographic Foil Sticker Button
- 30Tailwind Brutalist Concrete Slab Button
- 31Tailwind Mercury Bead Morph Button
- 32Tailwind Soft Pill Modern SaaS Button
- 33Tailwind Masking Tape Label Button
- 34Tailwind Obsidian Glass Shard Button
- 35Tailwind Wine Velvet Ribbon Button
- 36Tailwind LED Segment Display Button
- 37Tailwind Cassette Mixtape Label Button
- 38Tailwind Chalkboard Menu Button
- 39Tailwind Vinyl Record Sleeve Ripple Button
- 40Tailwind Polaroid Snapshot Button
- 41Tailwind Airline Boarding Pass Button
- 42Tailwind Aged Brass Subway Token Button
- 43Tailwind Vintage Rx Pharmacy Label Button
- 44Tailwind Bakelite Radio Dial Toggle Button
- 45Tailwind Regal Postage Stamp Button
- 46Tailwind Victorian Cigar Band Foil Button
- 47Tailwind Vintage Calculator Key Button
- 48Tailwind Toolbox Latch Spotlight Button
- 49Tailwind Receipt Paper Total Count-Up Button
- 50Tailwind IBM Punch Card Magnetic Follow Button
- 51Tailwind Brass Periscope Lens Button
Tailwind Lacquered Walnut Wood Button
Book-matched walnut under high-gloss lacquer: grain from four repeating gradients at incommensurate frequencies so it never visibly tiles, a brass inlay label cut with background-clip:text, and a gloss band that travels across the finish on hover.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tb-25 w-full min-h-svh grid place-items-center font-tb25-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-25__veneer group relative overflow-hidden isolate cursor-pointer min-h-16 px-10 border border-tb25-edge rounded-[0.65rem] text-xl font-semibold tracking-[0.06em] text-tb25-brass shadow-[inset_0_1px_0_#ffffff38,inset_0_-2px_4px_#00000073,0_16px_30px_-14px_#000000cc] transition-[translate,box-shadow,filter] duration-[220ms] ease-tb25-out before:content-[''] before:absolute before:inset-x-0 before:top-0 before:h-[38%] before:z-20 before:pointer-events-none before:rounded-t-[0.65rem] before:bg-[linear-gradient(180deg,rgba(255,255,255,0.16),transparent)] hover:-translate-y-0.5 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_3px_8px_#00000099] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb25-brass disabled:cursor-not-allowed disabled:grayscale-[0.6] disabled:brightness-80 motion-reduce:transition-none">
<span aria-hidden="true" class="absolute -inset-y-[20%] -inset-x-[30%] z-20 pointer-events-none -translate-x-[60%] bg-[linear-gradient(104deg,transparent_40%,rgba(255,255,255,0.34)_50%,transparent_60%)] transition-transform duration-[900ms] ease-tb25-out group-hover:translate-x-[60%] group-focus-visible:translate-x-[60%] motion-reduce:hidden"></span>
<span class="tb-25__inlay relative z-30 bg-[linear-gradient(180deg,#f6e3ae,#c99f4f_55%,#8d6a2c)] bg-clip-text text-transparent drop-shadow-[0_1px_0_#00000099]">Open the cabinet</span>
</button>
</div><div class="tb-25 w-full min-h-svh grid place-items-center font-tb25-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-25__veneer group relative overflow-hidden isolate cursor-pointer min-h-16 px-10 border border-tb25-edge rounded-[0.65rem] text-xl font-semibold tracking-[0.06em] text-tb25-brass shadow-[inset_0_1px_0_#ffffff38,inset_0_-2px_4px_#00000073,0_16px_30px_-14px_#000000cc] transition-[translate,box-shadow,filter] duration-[220ms] ease-tb25-out before:content-[''] before:absolute before:inset-x-0 before:top-0 before:h-[38%] before:z-20 before:pointer-events-none before:rounded-t-[0.65rem] before:bg-[linear-gradient(180deg,rgba(255,255,255,0.16),transparent)] hover:-translate-y-0.5 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_3px_8px_#00000099] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb25-brass disabled:cursor-not-allowed disabled:grayscale-[0.6] disabled:brightness-80 motion-reduce:transition-none">
<span aria-hidden="true" class="absolute -inset-y-[20%] -inset-x-[30%] z-20 pointer-events-none -translate-x-[60%] bg-[linear-gradient(104deg,transparent_40%,rgba(255,255,255,0.34)_50%,transparent_60%)] transition-transform duration-[900ms] ease-tb25-out group-hover:translate-x-[60%] group-focus-visible:translate-x-[60%] motion-reduce:hidden"></span>
<span class="tb-25__inlay relative z-30 bg-[linear-gradient(180deg,#f6e3ae,#c99f4f_55%,#8d6a2c)] bg-clip-text text-transparent drop-shadow-[0_1px_0_#00000099]">Open the cabinet</span>
</button>
</div>@import "tailwindcss";
@theme {
--color-tb25-bg: #120d09;
--color-tb25-bg: oklch(0.15 0.02 55);
--color-tb25-wood: #5b3a1f;
--color-tb25-wood: oklch(0.38 0.07 55);
--color-tb25-wood-hi: #7d5229;
--color-tb25-wood-hi: oklch(0.47 0.08 58);
--color-tb25-wood-lo: #33200f;
--color-tb25-wood-lo: oklch(0.25 0.05 52);
--color-tb25-edge: #22150b;
--color-tb25-edge: oklch(0.18 0.03 52);
--color-tb25-brass: #e8cd97;
--color-tb25-brass: oklch(0.86 0.06 85);
--font-tb25-serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb25-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-25 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, #d8a55e 12%, transparent), transparent 70%), var(--color-tb25-bg);
}
/* THE VENEER: four repeating gradients at 3/7/11/23px periods, each 1-3° off the
others so the grain wanders instead of tiling. Meaningless as separate values. */
.tb-25__veneer {
background-color: var(--color-tb25-wood);
background-image: repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px), repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px), repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px), repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px), linear-gradient(100deg, var(--color-tb25-wood-hi), var(--color-tb25-wood) 45%, var(--color-tb25-wood-lo));
}
@media (prefers-color-scheme: light) {
.tb-25:not([data-theme="dark"]) {
--color-tb25-bg: oklch(0.22 0.025 52);
}
}
.tb-25[data-theme="light"] {
--color-tb25-bg: oklch(0.22 0.025 52);
}
@media (forced-colors: active) {
.tb-25__veneer {
background: ButtonFace;
border: 1px solid ButtonText;
box-shadow: none;
}
.tb-25__inlay {
background: none;
color: ButtonText;
-webkit-text-fill-color: ButtonText;
filter: none;
}
.tb-25__veneer span[aria-hidden] {
display: none;
}
}@import "tailwindcss";
@theme {
--color-tb25-bg: #120d09;
--color-tb25-bg: oklch(0.15 0.02 55);
--color-tb25-wood: #5b3a1f;
--color-tb25-wood: oklch(0.38 0.07 55);
--color-tb25-wood-hi: #7d5229;
--color-tb25-wood-hi: oklch(0.47 0.08 58);
--color-tb25-wood-lo: #33200f;
--color-tb25-wood-lo: oklch(0.25 0.05 52);
--color-tb25-edge: #22150b;
--color-tb25-edge: oklch(0.18 0.03 52);
--color-tb25-brass: #e8cd97;
--color-tb25-brass: oklch(0.86 0.06 85);
--font-tb25-serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb25-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-25 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, #d8a55e 12%, transparent), transparent 70%), var(--color-tb25-bg);
}
/* THE VENEER: four repeating gradients at 3/7/11/23px periods, each 1-3° off the
others so the grain wanders instead of tiling. Meaningless as separate values. */
.tb-25__veneer {
background-color: var(--color-tb25-wood);
background-image: repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px), repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px), repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px), repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px), linear-gradient(100deg, var(--color-tb25-wood-hi), var(--color-tb25-wood) 45%, var(--color-tb25-wood-lo));
}
@media (prefers-color-scheme: light) {
.tb-25:not([data-theme="dark"]) {
--color-tb25-bg: oklch(0.22 0.025 52);
}
}
.tb-25[data-theme="light"] {
--color-tb25-bg: oklch(0.22 0.025 52);
}
@media (forced-colors: active) {
.tb-25__veneer {
background: ButtonFace;
border: 1px solid ButtonText;
box-shadow: none;
}
.tb-25__inlay {
background: none;
color: ButtonText;
-webkit-text-fill-color: ButtonText;
filter: none;
}
.tb-25__veneer span[aria-hidden] {
display: none;
}
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tb25-bg: #120d09;
--color-tb25-bg: oklch(0.15 0.02 55);
--color-tb25-wood: #5b3a1f;
--color-tb25-wood: oklch(0.38 0.07 55);
--color-tb25-wood-hi: #7d5229;
--color-tb25-wood-hi: oklch(0.47 0.08 58);
--color-tb25-wood-lo: #33200f;
--color-tb25-wood-lo: oklch(0.25 0.05 52);
--color-tb25-edge: #22150b;
--color-tb25-edge: oklch(0.18 0.03 52);
--color-tb25-brass: #e8cd97;
--color-tb25-brass: oklch(0.86 0.06 85);
--font-tb25-serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb25-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-25 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, #d8a55e 12%, transparent), transparent 70%), var(--color-tb25-bg);
}
/* THE VENEER: four repeating gradients at 3/7/11/23px periods, each 1-3° off the
others so the grain wanders instead of tiling. Meaningless as separate values. */
.tb-25__veneer {
background-color: var(--color-tb25-wood);
background-image: repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px), repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px), repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px), repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px), linear-gradient(100deg, var(--color-tb25-wood-hi), var(--color-tb25-wood) 45%, var(--color-tb25-wood-lo));
}
@media (prefers-color-scheme: light) {
.tb-25:not([data-theme="dark"]) {
--color-tb25-bg: oklch(0.22 0.025 52);
}
}
.tb-25[data-theme="light"] {
--color-tb25-bg: oklch(0.22 0.025 52);
}
@media (forced-colors: active) {
.tb-25__veneer {
background: ButtonFace;
border: 1px solid ButtonText;
box-shadow: none;
}
.tb-25__inlay {
background: none;
color: ButtonText;
-webkit-text-fill-color: ButtonText;
filter: none;
}
.tb-25__veneer span[aria-hidden] {
display: none;
}
}@import "tailwindcss";
@theme {
--color-tb25-bg: #120d09;
--color-tb25-bg: oklch(0.15 0.02 55);
--color-tb25-wood: #5b3a1f;
--color-tb25-wood: oklch(0.38 0.07 55);
--color-tb25-wood-hi: #7d5229;
--color-tb25-wood-hi: oklch(0.47 0.08 58);
--color-tb25-wood-lo: #33200f;
--color-tb25-wood-lo: oklch(0.25 0.05 52);
--color-tb25-edge: #22150b;
--color-tb25-edge: oklch(0.18 0.03 52);
--color-tb25-brass: #e8cd97;
--color-tb25-brass: oklch(0.86 0.06 85);
--font-tb25-serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb25-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-25 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, #d8a55e 12%, transparent), transparent 70%), var(--color-tb25-bg);
}
/* THE VENEER: four repeating gradients at 3/7/11/23px periods, each 1-3° off the
others so the grain wanders instead of tiling. Meaningless as separate values. */
.tb-25__veneer {
background-color: var(--color-tb25-wood);
background-image: repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px), repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px), repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px), repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px), linear-gradient(100deg, var(--color-tb25-wood-hi), var(--color-tb25-wood) 45%, var(--color-tb25-wood-lo));
}
@media (prefers-color-scheme: light) {
.tb-25:not([data-theme="dark"]) {
--color-tb25-bg: oklch(0.22 0.025 52);
}
}
.tb-25[data-theme="light"] {
--color-tb25-bg: oklch(0.22 0.025 52);
}
@media (forced-colors: active) {
.tb-25__veneer {
background: ButtonFace;
border: 1px solid ButtonText;
box-shadow: none;
}
.tb-25__inlay {
background: none;
color: ButtonText;
-webkit-text-fill-color: ButtonText;
filter: none;
}
.tb-25__veneer span[aria-hidden] {
display: none;
}
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Utilities: the plate box, the elevation and press shadows, the varnish sheen on
before:, the gloss sweep, and the brass inlay (bg-clip-text text-transparentover an arbitrary gradient, with the solid fallback colour declared first). CSS: the four-layer grain and the forced-colors override that has to un-transparent the text. text-tb25-brass bg-[linear-gradient(...)] bg-clip-text text-transparentin that order is the whole trick: the solid colour is the fallback, and it is visibly the fallback because it comes first. In CSS the same safety measure was a comment.- The forced-colors block needs
-webkit-text-fill-color: ButtonTextas well ascolor— clipped text ignorescoloralone in WebKit. That is exactly the kind of one-off that belongs in a stylesheet rather than a variant. - Third texture demo in a row, third time the paint stayed in CSS. The pattern is stable enough to state as a rule: if the value only means something as part of a stack of four or more, it is a recipe, not a token.
Here's a working CSS demo 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: Tailwind Lacquered Walnut Wood Button
Source: https://codefronts.com/components/tailwind-css-buttons/tailwind-lacquered-walnut-wood-button/
Book-matched walnut under high-gloss lacquer: grain from four repeating gradients at incommensurate frequencies so it never visibly tiles, a brass inlay label cut with background-clip:text, and a gloss band that travels across the finish on hover.
## HTML
```html
<div class="tb-25 w-full min-h-svh grid place-items-center font-tb25-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-25__veneer group relative overflow-hidden isolate cursor-pointer min-h-16 px-10 border border-tb25-edge rounded-[0.65rem] text-xl font-semibold tracking-[0.06em] text-tb25-brass shadow-[inset_0_1px_0_#ffffff38,inset_0_-2px_4px_#00000073,0_16px_30px_-14px_#000000cc] transition-[translate,box-shadow,filter] duration-[220ms] ease-tb25-out before:content-[''] before:absolute before:inset-x-0 before:top-0 before:h-[38%] before:z-20 before:pointer-events-none before:rounded-t-[0.65rem] before:bg-[linear-gradient(180deg,rgba(255,255,255,0.16),transparent)] hover:-translate-y-0.5 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_3px_8px_#00000099] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb25-brass disabled:cursor-not-allowed disabled:grayscale-[0.6] disabled:brightness-80 motion-reduce:transition-none">
<span aria-hidden="true" class="absolute -inset-y-[20%] -inset-x-[30%] z-20 pointer-events-none -translate-x-[60%] bg-[linear-gradient(104deg,transparent_40%,rgba(255,255,255,0.34)_50%,transparent_60%)] transition-transform duration-[900ms] ease-tb25-out group-hover:translate-x-[60%] group-focus-visible:translate-x-[60%] motion-reduce:hidden"></span>
<span class="tb-25__inlay relative z-30 bg-[linear-gradient(180deg,#f6e3ae,#c99f4f_55%,#8d6a2c)] bg-clip-text text-transparent drop-shadow-[0_1px_0_#00000099]">Open the cabinet</span>
</button>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tb25-bg: #120d09;
--color-tb25-bg: oklch(0.15 0.02 55);
--color-tb25-wood: #5b3a1f;
--color-tb25-wood: oklch(0.38 0.07 55);
--color-tb25-wood-hi: #7d5229;
--color-tb25-wood-hi: oklch(0.47 0.08 58);
--color-tb25-wood-lo: #33200f;
--color-tb25-wood-lo: oklch(0.25 0.05 52);
--color-tb25-edge: #22150b;
--color-tb25-edge: oklch(0.18 0.03 52);
--color-tb25-brass: #e8cd97;
--color-tb25-brass: oklch(0.86 0.06 85);
--font-tb25-serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb25-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-25 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, #d8a55e 12%, transparent), transparent 70%), var(--color-tb25-bg);
}
/* THE VENEER: four repeating gradients at 3/7/11/23px periods, each 1-3° off the
others so the grain wanders instead of tiling. Meaningless as separate values. */
.tb-25__veneer {
background-color: var(--color-tb25-wood);
background-image: repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px), repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px), repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px), repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px), linear-gradient(100deg, var(--color-tb25-wood-hi), var(--color-tb25-wood) 45%, var(--color-tb25-wood-lo));
}
@media (prefers-color-scheme: light) {
.tb-25:not([data-theme="dark"]) {
--color-tb25-bg: oklch(0.22 0.025 52);
}
}
.tb-25[data-theme="light"] {
--color-tb25-bg: oklch(0.22 0.025 52);
}
@media (forced-colors: active) {
.tb-25__veneer {
background: ButtonFace;
border: 1px solid ButtonText;
box-shadow: none;
}
.tb-25__inlay {
background: none;
color: ButtonText;
-webkit-text-fill-color: ButtonText;
filter: none;
}
.tb-25__veneer span[aria-hidden] {
display: none;
}
}
```Here's a working CSS demo 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: Tailwind Lacquered Walnut Wood Button
Source: https://codefronts.com/components/tailwind-css-buttons/tailwind-lacquered-walnut-wood-button/
Book-matched walnut under high-gloss lacquer: grain from four repeating gradients at incommensurate frequencies so it never visibly tiles, a brass inlay label cut with background-clip:text, and a gloss band that travels across the finish on hover.
## HTML
```html
<div class="tb-25 w-full min-h-svh grid place-items-center font-tb25-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-25__veneer group relative overflow-hidden isolate cursor-pointer min-h-16 px-10 border border-tb25-edge rounded-[0.65rem] text-xl font-semibold tracking-[0.06em] text-tb25-brass shadow-[inset_0_1px_0_#ffffff38,inset_0_-2px_4px_#00000073,0_16px_30px_-14px_#000000cc] transition-[translate,box-shadow,filter] duration-[220ms] ease-tb25-out before:content-[''] before:absolute before:inset-x-0 before:top-0 before:h-[38%] before:z-20 before:pointer-events-none before:rounded-t-[0.65rem] before:bg-[linear-gradient(180deg,rgba(255,255,255,0.16),transparent)] hover:-translate-y-0.5 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_3px_8px_#00000099] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb25-brass disabled:cursor-not-allowed disabled:grayscale-[0.6] disabled:brightness-80 motion-reduce:transition-none">
<span aria-hidden="true" class="absolute -inset-y-[20%] -inset-x-[30%] z-20 pointer-events-none -translate-x-[60%] bg-[linear-gradient(104deg,transparent_40%,rgba(255,255,255,0.34)_50%,transparent_60%)] transition-transform duration-[900ms] ease-tb25-out group-hover:translate-x-[60%] group-focus-visible:translate-x-[60%] motion-reduce:hidden"></span>
<span class="tb-25__inlay relative z-30 bg-[linear-gradient(180deg,#f6e3ae,#c99f4f_55%,#8d6a2c)] bg-clip-text text-transparent drop-shadow-[0_1px_0_#00000099]">Open the cabinet</span>
</button>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tb25-bg: #120d09;
--color-tb25-bg: oklch(0.15 0.02 55);
--color-tb25-wood: #5b3a1f;
--color-tb25-wood: oklch(0.38 0.07 55);
--color-tb25-wood-hi: #7d5229;
--color-tb25-wood-hi: oklch(0.47 0.08 58);
--color-tb25-wood-lo: #33200f;
--color-tb25-wood-lo: oklch(0.25 0.05 52);
--color-tb25-edge: #22150b;
--color-tb25-edge: oklch(0.18 0.03 52);
--color-tb25-brass: #e8cd97;
--color-tb25-brass: oklch(0.86 0.06 85);
--font-tb25-serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb25-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-25 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, #d8a55e 12%, transparent), transparent 70%), var(--color-tb25-bg);
}
/* THE VENEER: four repeating gradients at 3/7/11/23px periods, each 1-3° off the
others so the grain wanders instead of tiling. Meaningless as separate values. */
.tb-25__veneer {
background-color: var(--color-tb25-wood);
background-image: repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px), repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px), repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px), repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px), linear-gradient(100deg, var(--color-tb25-wood-hi), var(--color-tb25-wood) 45%, var(--color-tb25-wood-lo));
}
@media (prefers-color-scheme: light) {
.tb-25:not([data-theme="dark"]) {
--color-tb25-bg: oklch(0.22 0.025 52);
}
}
.tb-25[data-theme="light"] {
--color-tb25-bg: oklch(0.22 0.025 52);
}
@media (forced-colors: active) {
.tb-25__veneer {
background: ButtonFace;
border: 1px solid ButtonText;
box-shadow: none;
}
.tb-25__inlay {
background: none;
color: ButtonText;
-webkit-text-fill-color: ButtonText;
filter: none;
}
.tb-25__veneer span[aria-hidden] {
display: none;
}
}
```How this works
The grain stays CSS, and the reason is arithmetic. Believable wood needs gradient periods that share no factor — 3px, 7px, 11px, 23px — with 1–3° of angle variance between layers so the grain wanders:
.tb-25__veneer{
background-image:
repeating-linear-gradient(92deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px),
repeating-linear-gradient(88deg, rgba(0,0,0,.10) 0 2px, transparent 2px 7px),
repeating-linear-gradient(91deg, rgba(255,255,255,.055) 0 1px, transparent 1px 11px),
repeating-linear-gradient(89deg, rgba(0,0,0,.16) 0 3px, transparent 3px 23px),
linear-gradient(100deg, var(--wood-hi), var(--wood) 45%, var(--wood-lo));
}Five layers, four of them meaningless alone. This is the clearest "leave it in CSS" case in the fifty-one.
The inlay is the interesting port. bg-clip-text text-transparent are real utilities, so the brass gradient label is three classes — but the transparent text means a failed gradient erases the label, so a solid text-tb25-brass is declared before them in the class list as the fallback.
Make it yours
- Species is the three wood tokens: pale for oak, red-brown for mahogany, near-black for ebony.
- Vertical cut: rotate all four grain layers together (92deg → 2deg).
- Satin finish: lower the gloss band's alpha. Mirror polish: add a second band at 40% offset.
- Mother-of-pearl inlay: swap the brass gradient for cool greys with a blue midpoint.
- The
before:sheen height (38%) sets how thick the varnish reads.
Gotchas — read before shipping
bg-clip-text text-transparentmakes the label vanish if the gradient fails. Declare a solid colour first — this port does.- Gradient-filled text often passes automated contrast checks by luck, because tools sample one colour. Measure the darkest stop against the wood.
- Five repeating layers is the ceiling for a component this size; more will show on scroll.
- Identical grain angles look like corduroy. Vary each layer by 1–3°.
- A gloss sweep crossing the label hurts legibility mid-animation. Keep the band under 45% alpha.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
bg-clip-text emits the -webkit- prefix for Safari automatically. Repeating gradients and filter shadows are universal below Tailwind v4's floor.