Metallic gradients in CSS: chrome, gold, copper and rose gold

CSS recipes with hex codes for chrome, gold, copper and rose gold, plus brushed metal and a sheen.

Updated

A metallic gradient looks like metal when it copies what polished metal reflects: a bright sky above, a hard dark horizon a little below the middle, and a lighter ground reflection under it. A smooth fade from light grey to dark grey reads as plastic. The sharp jump at the horizon makes it read as chrome. In CSS that is one linear-gradient with two stops almost on top of each other:

.chrome {
  background: linear-gradient(
    180deg,
    #fdfdfe 0%,
    #c9ced6 36%,
    #59606b 49%,
    #20242a 50%,
    #747b86 62%,
    #dfe3e8 82%,
    #a6adb7 100%
  );
}

Swap the seven colours and the same stops give you gold, copper or rose gold. All of the swatches below are plain CSS, rendered in the browser:

Chrome
Gold
Copper
Rose gold
Brushed

Why the stops sit where they do

Each stop stands for something the metal reflects:

  • 0% to 36%, the sky. The top of the surface faces up and reflects open light, so it starts near white and falls off gently.
  • 49% and 50%, the horizon. Two stops one percent apart make a hard edge. This is the line where the reflected sky meets the reflected ground, and it is the part that sells the effect. Move them to 40% and 60% and the edge becomes a wide dark band, which reads as a soft satin tube rather than mirror chrome.
  • 62% to 82%, the ground. Below the horizon the metal reflects the floor and the room, which is darker than the sky but picks up a second highlight lower down.
  • 100%, the bottom edge. A slightly darker last stop curves the surface away from you.

The sky takes up a little more than the ground, so the horizon sits just below the middle, as it does when you look down at a curved, polished surface.

Gold, copper and rose gold

Metals other than silver tint their own reflections, so every stop takes the metal's hue, including the shadows. A gold gradient with a grey horizon looks like gold paint on steel. Use a dark brown for the horizon instead:

MetalSkyLightHorizon topHorizonGroundHighlightEdge
Chrome#fdfdfe#c9ced6#59606b#20242a#747b86#dfe3e8#a6adb7
Gold#fff7d6#e9c76b#8f5f17#4a2e07#a8741f#f6dc8e#b9862c
Copper#ffe3cf#e8956a#8a3f1c#3d1608#a8532b#f4b48e#b8562a
Rose gold#fff0ec#eab5a6#9c5f57#4f2a27#b57a6e#f7d3c8#c48b7f

The stops are the same for every row: 0%, 36%, 49%, 50%, 62%, 82% and 100%. If gold looks dull, push the horizon towards a deeper brown rather than towards black.

For a metal that matches a brand colour, keep the structure and pick the seven colours from one hue in OKLCH. The chrome row's lightness runs 0.99, 0.85, 0.49, 0.26, 0.58, 0.91 and 0.75; reuse those, keep chroma lowest at the top stop, and give the mid-tones the most.

Brushed metal

Brushed steel has fine parallel scratches. Stack three repeating-linear-gradient layers with different periods over a soft base gradient. Periods that don't divide each other (3, 7 and 13 pixels here) keep the pattern from lining up into visible stripes:

.brushed {
  background:
    repeating-linear-gradient(
      90deg,
      rgb(255 255 255 / 0) 0 2px,
      rgb(255 255 255 / 0.07) 2px 3px
    ),
    repeating-linear-gradient(
      90deg,
      rgb(0 0 0 / 0) 0 5px,
      rgb(0 0 0 / 0.06) 5px 7px
    ),
    repeating-linear-gradient(
      90deg,
      rgb(255 255 255 / 0) 0 11px,
      rgb(255 255 255 / 0.05) 11px 13px
    ),
    linear-gradient(180deg, #e7eaee, #a9afb8 55%, #c9ced5);
}

The scratch layers run at 90deg, so the lines are vertical. Turn all three to 0deg for horizontal brushing. Keep their opacity under about 0.1, or the texture looks like a barcode.

A metal knob with conic-gradient

A turned metal disc, like a volume knob or a watch dial, reflects light in a pattern that repeats as you go around the centre. conic-gradient draws exactly that. Repeat a light, dark, light, dark sequence twice around the circle:

.knob {
  width: 160px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: conic-gradient(
    #d7dbe0,
    #8a9099 12%,
    #f4f6f8 25%,
    #7d838c 37%,
    #d7dbe0 50%,
    #8a9099 62%,
    #f4f6f8 75%,
    #7d838c 87%,
    #d7dbe0
  );
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.4),
    0 6px 18px rgb(0 0 0 / 0.5);
}

The first and last colour must match, or a seam shows at 12 o'clock. The inset shadow draws a thin bright rim, which is where a real disc catches light on its bevel.

Chrome text

The chrome gradient also works on text. Clip the background to the glyphs and make the text colour transparent:

.chrome-text {
  font:
    800 72px/1 system-ui,
    sans-serif;
  background: linear-gradient(
    180deg,
    #fdfdfe 0%,
    #c9ced6 40%,
    #3a3f47 50%,
    #8d949e 62%,
    #eef1f4 85%
  );
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}

Use it on heavy, large type. On thin or small text the horizon line falls between strokes and the effect disappears. The gradient runs top to bottom across the element's height, so the horizon lands halfway down the line box, not halfway down the letters. Keep the heading on one line with line-height: 1 and no vertical padding, as above, and the horizon crosses the glyphs. If the text wraps to two lines, the horizon falls between them. Gradient text with Tailwind covers the Tailwind classes for the same trick.

An animated sheen

A highlight that sweeps across the surface makes static chrome look polished. Put it on a pseudo-element and slide it with transform, which the browser can animate on the compositor without repainting the gradient:

.sheen {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    105deg,
    transparent 40%,
    rgb(255 255 255 / 0.7) 50%,
    transparent 60%
  );
  transform: translateX(-100%);
  animation: sheen 3s ease-in-out infinite;
}

@keyframes sheen {
  60%,
  100% {
    transform: translateX(100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sheen::after {
    animation: none;
  }
}

isolation: isolate with z-index: -1 keeps the sheen above the element's background and below its text. The keyframes finish the sweep at 60%, so the highlight passes and then pauses before the next one instead of running non-stop.

Liquid chrome that moves

CSS gives you chrome that holds still, or one highlight that slides. Real liquid metal reflects light that streams along its folds as the surface moves, and that needs a shader. The Chrome collection has eight of them. Two are free: Mercury, in grey, white and slate, and Copper. Both run the chrome shader, which bends a set of long folds with slow noise and reflects a studio of soft light bands off them, so the highlights follow the folds and the troughs fall to black. This is Mercury:

Mercury, live

The three colours map to parts of the reflection: the first is the studio light the metal mostly shows, the second the hot highlight, and the third a cool rim at grazing angles. warp sets how much the surface folds and scale the size of the swells. It draws with WebGPU where the browser has it and WebGL2 otherwise. It loops seamlessly, leans a little toward the pointer, and shows one still frame to visitors who prefer reduced motion.

Mercury installs with the shadcn CLI and no account, into any React project with a components.json:

npx shadcn@latest add https://gradients.sh/r/c/eyJ2IjoxLCJwcmVzZXRJZCI6Im1lcmN1cnkiLCJuYW1lIjoiTWVyY3VyeSIsInAiOnsia2luZCI6ImNocm9tZSIsImJhY2tncm91bmQiOiIjMDQwNTA2IiwiY29sb3JzIjpbIiM4YzkyOWMiLCIjZmZmZmZmIiwiIzRhNTA2MCJdLCJpbnRlcmFjdGlvbiI6eyJwb2ludGVyIjowLjE1LCJzY3JvbGwiOjAuMn0sImxvb3BTZWNvbmRzIjozMCwic2NhbGUiOjAuNiwic2VlZCI6MzAsInNwZWVkIjowLjIsIndhcnAiOjAuOX19.json
components/hero.tsx
import { Mercury } from "@/components/gradients/mercury";

export function Hero() {
  return (
    <section className="relative isolate min-h-[560px]">
      <Mercury className="absolute inset-0 -z-10" />
      {/* Your content sits on top. */}
    </section>
  );
}

To use chrome as an image or a video instead, open Mercury or Copper in the studio, change the colours to gold or rose gold if you like, and export. A free account exports PNGs up to 1920px wide and 10-second MP4 loops up to 1080p60. Mercury's own loop is 30 seconds, so set Loop to 10 seconds or less before a free MP4 export, or the video cuts the loop short.