21 / 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 Brushed Brass Plate Button
A machined brass nameplate: horizontal brush grain from stacked repeating gradients, four countersunk screws, engraved letterforms cut with a two-shadow bevel, and a specular band that sweeps across the metal on hover. The grain is the collection's first clear case for keeping paint in CSS.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tb-21 w-full min-h-svh grid place-items-center font-tb21-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-21__plate group relative overflow-hidden isolate cursor-pointer min-h-16 px-12 border border-tb21-brass-lo rounded-lg text-base font-semibold uppercase tracking-[0.16em] text-tb21-engrave [text-shadow:0_1px_0_#ffffff8c,0_-1px_0_#0000006b] shadow-[inset_0_1px_0_#ffffff73,inset_0_-1px_0_#00000059,0_14px_26px_-14px_#000000bf] transition-[translate,box-shadow,filter] duration-200 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_2px_6px_#00000080] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb21-brass-hi disabled:cursor-not-allowed disabled:grayscale-[0.7] disabled:brightness-[0.85] motion-reduce:transition-none">
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 left-2.5 size-2.5 rounded-full transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 right-2.5 size-2.5 rounded-full rotate-[34deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 left-2.5 size-2.5 rounded-full -rotate-[22deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 right-2.5 size-2.5 rounded-full rotate-[12deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="absolute inset-0 z-20 pointer-events-none -translate-x-[62%] bg-[linear-gradient(100deg,transparent_38%,rgba(255,255,255,0.42)_50%,transparent_62%)] transition-transform duration-[850ms] ease-tb21-out group-hover:translate-x-[62%] group-focus-visible:translate-x-[62%] motion-reduce:hidden"></span>
<span class="relative z-40">Reserve a table</span>
</button>
</div><div class="tb-21 w-full min-h-svh grid place-items-center font-tb21-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-21__plate group relative overflow-hidden isolate cursor-pointer min-h-16 px-12 border border-tb21-brass-lo rounded-lg text-base font-semibold uppercase tracking-[0.16em] text-tb21-engrave [text-shadow:0_1px_0_#ffffff8c,0_-1px_0_#0000006b] shadow-[inset_0_1px_0_#ffffff73,inset_0_-1px_0_#00000059,0_14px_26px_-14px_#000000bf] transition-[translate,box-shadow,filter] duration-200 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_2px_6px_#00000080] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb21-brass-hi disabled:cursor-not-allowed disabled:grayscale-[0.7] disabled:brightness-[0.85] motion-reduce:transition-none">
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 left-2.5 size-2.5 rounded-full transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 right-2.5 size-2.5 rounded-full rotate-[34deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 left-2.5 size-2.5 rounded-full -rotate-[22deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 right-2.5 size-2.5 rounded-full rotate-[12deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="absolute inset-0 z-20 pointer-events-none -translate-x-[62%] bg-[linear-gradient(100deg,transparent_38%,rgba(255,255,255,0.42)_50%,transparent_62%)] transition-transform duration-[850ms] ease-tb21-out group-hover:translate-x-[62%] group-focus-visible:translate-x-[62%] motion-reduce:hidden"></span>
<span class="relative z-40">Reserve a table</span>
</button>
</div>@import "tailwindcss";
@theme {
--color-tb21-bg: #171310;
--color-tb21-bg: oklch(0.18 0.015 60);
--color-tb21-brass: #b08d4f;
--color-tb21-brass: oklch(0.66 0.08 82);
--color-tb21-brass-hi: #e6cd94;
--color-tb21-brass-hi: oklch(0.86 0.08 88);
--color-tb21-brass-lo: #7d6132;
--color-tb21-brass-lo: oklch(0.48 0.07 80);
--color-tb21-engrave: #3d2d12;
--color-tb21-engrave: oklch(0.29 0.05 72);
--font-tb21-serif: "Cinzel", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb21-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, var(--color-tb21-brass) 14%, transparent), transparent 70%), var(--color-tb21-bg);
}
/* THE GRAIN. Three repeating gradients at 5px / 7px periods over a diagonal base —
one indivisible texture recipe, illegible as an arbitrary utility. */
.tb-21__plate {
background-color: var(--color-tb21-brass);
background-image: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px, rgba(0,0,0,.07) 2px 3px, transparent 3px 5px), repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px), linear-gradient(112deg, var(--color-tb21-brass-hi), var(--color-tb21-brass) 34%, var(--color-tb21-brass-lo) 62%, var(--color-tb21-brass) 86%);
}
/* Countersunk screw head + slot. The slot is a clipped pseudo-element. */
.tb-21__screw {
background: radial-gradient(circle at 35% 30%, #f0e0b8, #8d6f38 60%, #5c4520);
box-shadow: inset 0 -1px 1px rgba(0,0,0,.5), 0 1px 1px rgba(255,255,255,.25);
}
.tb-21__screw::after {
content: '';
position: absolute;
inset: 22% 12%;
background: rgba(0,0,0,.55);
clip-path: polygon(0 42%, 100% 42%, 100% 58%, 0 58%);
}
@media (prefers-color-scheme: light) {
.tb-21:not([data-theme="dark"]) {
--color-tb21-bg: oklch(0.28 0.02 60);
}
}
.tb-21[data-theme="light"] {
--color-tb21-bg: oklch(0.28 0.02 60);
}
@media (forced-colors: active) {
.tb-21__plate {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
text-shadow: none;
box-shadow: none;
}
.tb-21__plate span[aria-hidden] {
display: none;
}
}@import "tailwindcss";
@theme {
--color-tb21-bg: #171310;
--color-tb21-bg: oklch(0.18 0.015 60);
--color-tb21-brass: #b08d4f;
--color-tb21-brass: oklch(0.66 0.08 82);
--color-tb21-brass-hi: #e6cd94;
--color-tb21-brass-hi: oklch(0.86 0.08 88);
--color-tb21-brass-lo: #7d6132;
--color-tb21-brass-lo: oklch(0.48 0.07 80);
--color-tb21-engrave: #3d2d12;
--color-tb21-engrave: oklch(0.29 0.05 72);
--font-tb21-serif: "Cinzel", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb21-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, var(--color-tb21-brass) 14%, transparent), transparent 70%), var(--color-tb21-bg);
}
/* THE GRAIN. Three repeating gradients at 5px / 7px periods over a diagonal base —
one indivisible texture recipe, illegible as an arbitrary utility. */
.tb-21__plate {
background-color: var(--color-tb21-brass);
background-image: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px, rgba(0,0,0,.07) 2px 3px, transparent 3px 5px), repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px), linear-gradient(112deg, var(--color-tb21-brass-hi), var(--color-tb21-brass) 34%, var(--color-tb21-brass-lo) 62%, var(--color-tb21-brass) 86%);
}
/* Countersunk screw head + slot. The slot is a clipped pseudo-element. */
.tb-21__screw {
background: radial-gradient(circle at 35% 30%, #f0e0b8, #8d6f38 60%, #5c4520);
box-shadow: inset 0 -1px 1px rgba(0,0,0,.5), 0 1px 1px rgba(255,255,255,.25);
}
.tb-21__screw::after {
content: '';
position: absolute;
inset: 22% 12%;
background: rgba(0,0,0,.55);
clip-path: polygon(0 42%, 100% 42%, 100% 58%, 0 58%);
}
@media (prefers-color-scheme: light) {
.tb-21:not([data-theme="dark"]) {
--color-tb21-bg: oklch(0.28 0.02 60);
}
}
.tb-21[data-theme="light"] {
--color-tb21-bg: oklch(0.28 0.02 60);
}
@media (forced-colors: active) {
.tb-21__plate {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
text-shadow: none;
box-shadow: none;
}
.tb-21__plate 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-tb21-bg: #171310;
--color-tb21-bg: oklch(0.18 0.015 60);
--color-tb21-brass: #b08d4f;
--color-tb21-brass: oklch(0.66 0.08 82);
--color-tb21-brass-hi: #e6cd94;
--color-tb21-brass-hi: oklch(0.86 0.08 88);
--color-tb21-brass-lo: #7d6132;
--color-tb21-brass-lo: oklch(0.48 0.07 80);
--color-tb21-engrave: #3d2d12;
--color-tb21-engrave: oklch(0.29 0.05 72);
--font-tb21-serif: "Cinzel", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb21-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, var(--color-tb21-brass) 14%, transparent), transparent 70%), var(--color-tb21-bg);
}
/* THE GRAIN. Three repeating gradients at 5px / 7px periods over a diagonal base —
one indivisible texture recipe, illegible as an arbitrary utility. */
.tb-21__plate {
background-color: var(--color-tb21-brass);
background-image: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px, rgba(0,0,0,.07) 2px 3px, transparent 3px 5px), repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px), linear-gradient(112deg, var(--color-tb21-brass-hi), var(--color-tb21-brass) 34%, var(--color-tb21-brass-lo) 62%, var(--color-tb21-brass) 86%);
}
/* Countersunk screw head + slot. The slot is a clipped pseudo-element. */
.tb-21__screw {
background: radial-gradient(circle at 35% 30%, #f0e0b8, #8d6f38 60%, #5c4520);
box-shadow: inset 0 -1px 1px rgba(0,0,0,.5), 0 1px 1px rgba(255,255,255,.25);
}
.tb-21__screw::after {
content: '';
position: absolute;
inset: 22% 12%;
background: rgba(0,0,0,.55);
clip-path: polygon(0 42%, 100% 42%, 100% 58%, 0 58%);
}
@media (prefers-color-scheme: light) {
.tb-21:not([data-theme="dark"]) {
--color-tb21-bg: oklch(0.28 0.02 60);
}
}
.tb-21[data-theme="light"] {
--color-tb21-bg: oklch(0.28 0.02 60);
}
@media (forced-colors: active) {
.tb-21__plate {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
text-shadow: none;
box-shadow: none;
}
.tb-21__plate span[aria-hidden] {
display: none;
}
}@import "tailwindcss";
@theme {
--color-tb21-bg: #171310;
--color-tb21-bg: oklch(0.18 0.015 60);
--color-tb21-brass: #b08d4f;
--color-tb21-brass: oklch(0.66 0.08 82);
--color-tb21-brass-hi: #e6cd94;
--color-tb21-brass-hi: oklch(0.86 0.08 88);
--color-tb21-brass-lo: #7d6132;
--color-tb21-brass-lo: oklch(0.48 0.07 80);
--color-tb21-engrave: #3d2d12;
--color-tb21-engrave: oklch(0.29 0.05 72);
--font-tb21-serif: "Cinzel", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb21-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, var(--color-tb21-brass) 14%, transparent), transparent 70%), var(--color-tb21-bg);
}
/* THE GRAIN. Three repeating gradients at 5px / 7px periods over a diagonal base —
one indivisible texture recipe, illegible as an arbitrary utility. */
.tb-21__plate {
background-color: var(--color-tb21-brass);
background-image: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px, rgba(0,0,0,.07) 2px 3px, transparent 3px 5px), repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px), linear-gradient(112deg, var(--color-tb21-brass-hi), var(--color-tb21-brass) 34%, var(--color-tb21-brass-lo) 62%, var(--color-tb21-brass) 86%);
}
/* Countersunk screw head + slot. The slot is a clipped pseudo-element. */
.tb-21__screw {
background: radial-gradient(circle at 35% 30%, #f0e0b8, #8d6f38 60%, #5c4520);
box-shadow: inset 0 -1px 1px rgba(0,0,0,.5), 0 1px 1px rgba(255,255,255,.25);
}
.tb-21__screw::after {
content: '';
position: absolute;
inset: 22% 12%;
background: rgba(0,0,0,.55);
clip-path: polygon(0 42%, 100% 42%, 100% 58%, 0 58%);
}
@media (prefers-color-scheme: light) {
.tb-21:not([data-theme="dark"]) {
--color-tb21-bg: oklch(0.28 0.02 60);
}
}
.tb-21[data-theme="light"] {
--color-tb21-bg: oklch(0.28 0.02 60);
}
@media (forced-colors: active) {
.tb-21__plate {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
text-shadow: none;
box-shadow: none;
}
.tb-21__plate 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=Cinzel: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=Cinzel:wght@500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Utilities: the plate's box, the engraved text-shadow, the elevation stack, the press travel, the sheen sweep, all four screws' positions and rotations, every state. CSS: the brush-grain background (six layers), the screw head's radial gradient and its slot pseudo-element.
- This is the first demo where the port deliberately stops. The grain as an arbitrary utility is a ~300-character class with eighteen underscore escapes; as three CSS lines it is legible and editable. The test the collection applies: would a designer tune this value? A brush-grain frequency stack, no. A sheen duration, yes — so that one is a utility.
- The screws show the opposite decision on the same element: their position and rotation are design values (utilities), their head shading is a texture recipe (CSS). Splitting one element's styling across both layers by that rule is normal, not a smell.
- A11y fix from the CSS original:
--engravewasoklch(0.33 0.05 72)against a mid-plate aroundoklch(0.66)— roughly 3.4:1, under the minimum for 16px text. The port darkens it to0.29(≈4.6:1). Engraving is meant to be subtle, not unreadable.
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 Brushed Brass Plate Button
Source: https://codefronts.com/components/tailwind-css-buttons/tailwind-brushed-brass-plate-button/
A machined brass nameplate: horizontal brush grain from stacked repeating gradients, four countersunk screws, engraved letterforms cut with a two-shadow bevel, and a specular band that sweeps across the metal on hover. The grain is the collection's first clear case for keeping paint in CSS.
## HTML
```html
<div class="tb-21 w-full min-h-svh grid place-items-center font-tb21-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-21__plate group relative overflow-hidden isolate cursor-pointer min-h-16 px-12 border border-tb21-brass-lo rounded-lg text-base font-semibold uppercase tracking-[0.16em] text-tb21-engrave [text-shadow:0_1px_0_#ffffff8c,0_-1px_0_#0000006b] shadow-[inset_0_1px_0_#ffffff73,inset_0_-1px_0_#00000059,0_14px_26px_-14px_#000000bf] transition-[translate,box-shadow,filter] duration-200 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_2px_6px_#00000080] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb21-brass-hi disabled:cursor-not-allowed disabled:grayscale-[0.7] disabled:brightness-[0.85] motion-reduce:transition-none">
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 left-2.5 size-2.5 rounded-full transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 right-2.5 size-2.5 rounded-full rotate-[34deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 left-2.5 size-2.5 rounded-full -rotate-[22deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 right-2.5 size-2.5 rounded-full rotate-[12deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="absolute inset-0 z-20 pointer-events-none -translate-x-[62%] bg-[linear-gradient(100deg,transparent_38%,rgba(255,255,255,0.42)_50%,transparent_62%)] transition-transform duration-[850ms] ease-tb21-out group-hover:translate-x-[62%] group-focus-visible:translate-x-[62%] motion-reduce:hidden"></span>
<span class="relative z-40">Reserve a table</span>
</button>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tb21-bg: #171310;
--color-tb21-bg: oklch(0.18 0.015 60);
--color-tb21-brass: #b08d4f;
--color-tb21-brass: oklch(0.66 0.08 82);
--color-tb21-brass-hi: #e6cd94;
--color-tb21-brass-hi: oklch(0.86 0.08 88);
--color-tb21-brass-lo: #7d6132;
--color-tb21-brass-lo: oklch(0.48 0.07 80);
--color-tb21-engrave: #3d2d12;
--color-tb21-engrave: oklch(0.29 0.05 72);
--font-tb21-serif: "Cinzel", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb21-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, var(--color-tb21-brass) 14%, transparent), transparent 70%), var(--color-tb21-bg);
}
/* THE GRAIN. Three repeating gradients at 5px / 7px periods over a diagonal base —
one indivisible texture recipe, illegible as an arbitrary utility. */
.tb-21__plate {
background-color: var(--color-tb21-brass);
background-image: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px, rgba(0,0,0,.07) 2px 3px, transparent 3px 5px), repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px), linear-gradient(112deg, var(--color-tb21-brass-hi), var(--color-tb21-brass) 34%, var(--color-tb21-brass-lo) 62%, var(--color-tb21-brass) 86%);
}
/* Countersunk screw head + slot. The slot is a clipped pseudo-element. */
.tb-21__screw {
background: radial-gradient(circle at 35% 30%, #f0e0b8, #8d6f38 60%, #5c4520);
box-shadow: inset 0 -1px 1px rgba(0,0,0,.5), 0 1px 1px rgba(255,255,255,.25);
}
.tb-21__screw::after {
content: '';
position: absolute;
inset: 22% 12%;
background: rgba(0,0,0,.55);
clip-path: polygon(0 42%, 100% 42%, 100% 58%, 0 58%);
}
@media (prefers-color-scheme: light) {
.tb-21:not([data-theme="dark"]) {
--color-tb21-bg: oklch(0.28 0.02 60);
}
}
.tb-21[data-theme="light"] {
--color-tb21-bg: oklch(0.28 0.02 60);
}
@media (forced-colors: active) {
.tb-21__plate {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
text-shadow: none;
box-shadow: none;
}
.tb-21__plate 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 Brushed Brass Plate Button
Source: https://codefronts.com/components/tailwind-css-buttons/tailwind-brushed-brass-plate-button/
A machined brass nameplate: horizontal brush grain from stacked repeating gradients, four countersunk screws, engraved letterforms cut with a two-shadow bevel, and a specular band that sweeps across the metal on hover. The grain is the collection's first clear case for keeping paint in CSS.
## HTML
```html
<div class="tb-21 w-full min-h-svh grid place-items-center font-tb21-serif p-[clamp(1.5rem,6vw,4rem)]">
<button type="button" class="tb-21__plate group relative overflow-hidden isolate cursor-pointer min-h-16 px-12 border border-tb21-brass-lo rounded-lg text-base font-semibold uppercase tracking-[0.16em] text-tb21-engrave [text-shadow:0_1px_0_#ffffff8c,0_-1px_0_#0000006b] shadow-[inset_0_1px_0_#ffffff73,inset_0_-1px_0_#00000059,0_14px_26px_-14px_#000000bf] transition-[translate,box-shadow,filter] duration-200 hover:brightness-105 active:translate-y-px active:shadow-[inset_0_2px_6px_#00000080] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tb21-brass-hi disabled:cursor-not-allowed disabled:grayscale-[0.7] disabled:brightness-[0.85] motion-reduce:transition-none">
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 left-2.5 size-2.5 rounded-full transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 top-2 right-2.5 size-2.5 rounded-full rotate-[34deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 left-2.5 size-2.5 rounded-full -rotate-[22deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="tb-21__screw absolute z-30 bottom-2 right-2.5 size-2.5 rounded-full rotate-[12deg] transition-[rotate] duration-300 group-active:rotate-[12deg] motion-reduce:transition-none"></span>
<span aria-hidden="true" class="absolute inset-0 z-20 pointer-events-none -translate-x-[62%] bg-[linear-gradient(100deg,transparent_38%,rgba(255,255,255,0.42)_50%,transparent_62%)] transition-transform duration-[850ms] ease-tb21-out group-hover:translate-x-[62%] group-focus-visible:translate-x-[62%] motion-reduce:hidden"></span>
<span class="relative z-40">Reserve a table</span>
</button>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tb21-bg: #171310;
--color-tb21-bg: oklch(0.18 0.015 60);
--color-tb21-brass: #b08d4f;
--color-tb21-brass: oklch(0.66 0.08 82);
--color-tb21-brass-hi: #e6cd94;
--color-tb21-brass-hi: oklch(0.86 0.08 88);
--color-tb21-brass-lo: #7d6132;
--color-tb21-brass-lo: oklch(0.48 0.07 80);
--color-tb21-engrave: #3d2d12;
--color-tb21-engrave: oklch(0.29 0.05 72);
--font-tb21-serif: "Cinzel", ui-serif, Georgia, "Times New Roman", serif;
--ease-tb21-out: cubic-bezier(0.16, 1, 0.3, 1);
}
.tb-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: radial-gradient(40rem 24rem at 50% 40%, color-mix(in oklab, var(--color-tb21-brass) 14%, transparent), transparent 70%), var(--color-tb21-bg);
}
/* THE GRAIN. Three repeating gradients at 5px / 7px periods over a diagonal base —
one indivisible texture recipe, illegible as an arbitrary utility. */
.tb-21__plate {
background-color: var(--color-tb21-brass);
background-image: repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px, rgba(0,0,0,.07) 2px 3px, transparent 3px 5px), repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px), linear-gradient(112deg, var(--color-tb21-brass-hi), var(--color-tb21-brass) 34%, var(--color-tb21-brass-lo) 62%, var(--color-tb21-brass) 86%);
}
/* Countersunk screw head + slot. The slot is a clipped pseudo-element. */
.tb-21__screw {
background: radial-gradient(circle at 35% 30%, #f0e0b8, #8d6f38 60%, #5c4520);
box-shadow: inset 0 -1px 1px rgba(0,0,0,.5), 0 1px 1px rgba(255,255,255,.25);
}
.tb-21__screw::after {
content: '';
position: absolute;
inset: 22% 12%;
background: rgba(0,0,0,.55);
clip-path: polygon(0 42%, 100% 42%, 100% 58%, 0 58%);
}
@media (prefers-color-scheme: light) {
.tb-21:not([data-theme="dark"]) {
--color-tb21-bg: oklch(0.28 0.02 60);
}
}
.tb-21[data-theme="light"] {
--color-tb21-bg: oklch(0.28 0.02 60);
}
@media (forced-colors: active) {
.tb-21__plate {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
text-shadow: none;
box-shadow: none;
}
.tb-21__plate span[aria-hidden] {
display: none;
}
}
```How this works
The grain stays in the stylesheet, and the notes say why. Three stacked repeating-linear-gradients at 1px/2px/5px periods plus a diagonal base is one texture recipe — six background layers that only make sense together:
.tb-21__plate{
background:
repeating-linear-gradient(90deg, rgba(255,255,255,.10) 0 1px, transparent 1px 2px,
rgba(0,0,0,.07) 2px 3px, transparent 3px 5px),
repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1px, transparent 1px 7px),
linear-gradient(112deg, var(--brass-hi), var(--brass) 34%, var(--brass-lo) 62%, var(--brass) 86%);
}As an arbitrary utility that is a 300-character class with eighteen underscores. Nobody would edit it, which means it has stopped being a design decision and become a liability.
Everything else is utilities, including the screws: each is a size-2.5 rounded-full span with a radial-gradient background and its own rest rotation, positioned by top-2 left-2.5 and friends. The slot is an after: pseudo-element with a clip-path bar.
Make it yours
- Steel or copper: edit the three brass tokens. The grain is colour-independent.
- Vertical cut: change
90degto0degin both repeating gradients. - Remove the screws for a floating plate, or keep two for a hinged look.
- Deepen the engraving by raising both text-shadow alphas equally — unequal values look painted.
- The sheen's
duration-[850ms]is the slowest in the collection; metal wants a lazy highlight.
Gotchas — read before shipping
- Engraved text is inherently low-contrast. Keep it large and bold, and measure against the plate's mid-tone, not the highlight.
- 1px repeating gradients shimmer on fractional-DPR screens. Whole-pixel stops, and never animate the grain's background position.
- Six background layers plus a moving highlight is the practical paint ceiling for a component this size. Never on a list item.
- Metal implies a physical press. Without real
active:travel it feels dead. - Forced-colors drops all texture — keep the border and label legible or the plate stops reading as a control.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Repeating gradients, layered text-shadow and clip-path are universal below Tailwind v4's own floor.