Back to blog
11 min readParallel Studio

CSS Chrome Button: How to Make a Metallic Button (Free Generator)

chrome buttonmetallic buttoncssbuttonwebflowframertailwindfree tool

A chrome button looks like polished metal: bright on top, a dark band through the middle, light again underneath, with a glint of light across it. This post shows how to build one in pure CSS with no image file, and how to drop it into HTML, Webflow, Framer, WordPress, Shopify or a React + Tailwind project.

If you'd rather not write it by hand, the free chrome button generator outputs the CSS, Tailwind classes and HTML for you. The examples below follow the same shape as its output.

Why a gradient reads as chrome

Polished metal is mostly reflection: a bright sky, a dark horizon and a lighter floor. A linear-gradient() with several close stops fakes that. Light at the top, a sharp dark band just past the middle, light again underneath.

Everything else in the effect is detail on top of that one gradient: a highlight, a rim, and a few shadows.

The metal body

Here is the chrome gradient the generator uses, as a button background:

.chrome-btn {
  background-color: #b2b9c2; /* fallback */
  background-image: linear-gradient(
    180deg,
    #fbfcfd 0%,
    #dde1e6 18%,
    #9aa2ad 44%,
    #5f6772 50%,
    #b2b9c2 56%,
    #eef1f4 80%,
    #c0c6ce 100%
  );
}

How it works:

  • The stops make the horizon. The jump from #9aa2ad at 44% to #5f6772 at 50% and back to #b2b9c2 at 56% is the dark band. Moving those stops changes how sharp the metal looks.
  • The angle sets where the light comes from. 180deg points down, so the bright "sky" is at the top. The generator lets you set any angle from 0 to 359.
  • A solid background-color sits underneath as a fallback, using one mid-tone from the same finish.

The generator has eight finishes, each with its own set of stops: chrome, silver, gold, copper, gunmetal, brushed steel, black chrome and rose gold. A tinted finish is the same structure with different colors.

Shine: contrast of the bands

The shine control (0 to 100) changes how far apart the stops are. The generator averages the finish's stop colors, then pulls each stop toward that average at low shine and pushes it away at high shine. Low shine gives a flatter, satin look. High shine gives a harder mirror.

Shine also sets the opacity of the white highlight and of the thin light line along the top edge, so the whole button gets glossier together. The stops in the snippets here are shown at full contrast; the tool scales them to your shine setting when it writes the CSS.

The highlight layer

On top of the body sits a soft white glint, added as a second background layer. The generator offers three highlight options: a radial glint, a conic sheen, or none.

.chrome-btn {
  background-image:
    radial-gradient(ellipse 50% 50% at 50% 50%, rgba(255,255,255,0.56) 0%, rgba(255,255,255,0.2) 30%, rgba(255,255,255,0) 62%),
    linear-gradient(180deg, #fbfcfd 0%, #dde1e6 18%, #9aa2ad 44%, #5f6772 50%, #b2b9c2 56%, #eef1f4 80%, #c0c6ce 100%);
  background-size: 200% 200%, 100% 100%;
  background-position: 50% 88%, 0 0;
  background-repeat: no-repeat, no-repeat;
}

The trick is the size. The highlight layer is 200% 200%, twice the button, so background-position can slide it. At rest it sits near the lit edge. The first layer in the list paints on top, so the glint is above the metal.

The conic option uses a conic-gradient() with two narrow bright wedges instead, which reads like a star or sheen across the surface. Brushed steel also adds a thin repeating vertical-line layer for grain.

The bevelled rim

The rim is a border painted with the same gradient turned 180 degrees, so the edge catches light on the opposite side from the body. It takes three declarations working together:

.chrome-btn {
  border: 2px solid transparent;
  background-origin: border-box;
  background-clip: padding-box, border-box;
  background-image:
    linear-gradient(180deg, /* body stops */ #fbfcfd 0%, #c0c6ce 100%),
    linear-gradient(0deg, /* same stops, reversed light */ #fbfcfd 0%, #c0c6ce 100%);
}

The border is transparent, so the background shows through it. The first layer is clipped to the padding-box, so it stops at the border. The second layer is clipped to the border-box, so it fills the border and, being underneath, only shows there. The result is a thin edge lit from the other side. In the real output the stop lists are the full ones from above, and the highlight layer sits on top of both.

The generator's rim goes from 0 (none) to 6px. Corner radius goes from 0 to 40px, and the default of 40px makes a pill.

Shadows: top edge, bottom edge, drop

Four shadows finish the look:

.chrome-btn {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.69),   /* light line on the top edge */
    inset 0 -1px 0 rgba(0,0,0,0.3),         /* dark line on the bottom edge */
    0 1px 2px rgba(0,0,0,0.3),              /* tight contact shadow */
    0 10px 24px -10px rgba(0,0,0,0.9);      /* soft drop shadow */
}

The two inset lines give the button thickness. The last shadow is a soft drop that lifts it off the page. The negative spread keeps it tucked under the button instead of forming a wide halo.

The top-line opacity follows the shine setting. The drop shadow depends on your background: the generator uses a heavier one (0.9 alpha) on a dark background and a lighter one (0.45) on a light background, so the shadow stays visible on both.

The label

The label is plain text in a dark ink, with a small embossed text-shadow:

.chrome-btn {
  color: #101318;
  text-shadow: 0 -1px 0 rgba(0,0,0,0.45);
  font-weight: 600;
  letter-spacing: -0.01em;
}

Each finish has its own label color. Dark labels (chrome, silver, gold, copper, brushed steel, rose gold) get the shadow shown above. Light labels on dark metal (gunmetal and black chrome) get a light shadow instead: 0 1px 0 rgba(255,255,255,0.55).

The generator has three sizes. Small is 14px text with 10px 20px padding, medium is 16px with 14px 30px, and large is 19px with 18px 40px. The label is capped at 32 characters.

Hover and active states

Hover moves the highlight. The tool writes a second background-position for the glint to slide to, and a transition so it travels instead of jumping:

.chrome-btn {
  transition: background-position 0.6s ease, box-shadow 0.2s ease, filter 0.2s ease;
}
.chrome-btn:hover {
  background-position: 50% 30%, 0 0;
}
.chrome-btn:active {
  filter: brightness(0.96);
}

The highlight slides from near the lit edge toward the far side, so the light seems to sweep across the surface. If you turn the highlight off, there is nothing to slide, so the generator falls back to filter: brightness(1.06) on hover instead.

The press state is a slight darkening with brightness(0.96). It's a small change, but it gives the button a response when clicked.

Accessibility

  • Use a real <button> (or <a>). The CSS is only paint. Keyboard, focus and screen readers keep working as usual, with no extra ARIA needed.

  • Add a focus-visible ring. The generator writes one, and it picks a color that reads on your chosen background: near-white on dark backgrounds and near-black on light ones.

    .chrome-btn:focus-visible {
      outline: 2px solid #f6f6f5;
      outline-offset: 3px;
    }
    

    The offset keeps the ring clear of the metal, so it doesn't blend into the edge.

  • Respect reduced motion. The button has a transition, so the generator adds a media query that removes it:

    @media (prefers-reduced-motion: reduce) {
      .chrome-btn {
        transition: none;
      }
    }
    

    With it on, the highlight jumps to its hover position without sliding.

  • Check label contrast on the real button. The label sits across the middle of the metal, which is exactly where the gradient has its dark band, with the white highlight on top of it. That makes this a button where it pays to test. Check the label against the darkest and lightest parts of the surface, not just the average, with a contrast checker. Low shine flattens the bands and can help, but check it rather than assume.

  • Don't rely on the shine to show state. Hover is a nice extra, not the only signal. Keep the focus ring for keyboard users.

Dark vs light backgrounds

The button itself is the same on any page, but two things depend on the surface it sits on:

  • The drop shadow. On a dark page the shadow is stronger so it still shows. On a light page it's softer so it doesn't look like a smudge.
  • The focus ring. Near-white on dark, near-black on light.

Set your page background in the generator's background field and it picks both for you. A bright chrome button on near-black looks strong, and a darker finish such as gunmetal or black chrome often looks better on a light page. For an accent, an ember orange like #e8794a on the page background or nearby text pairs well with a cool neutral finish. The generator's preview shows what you'll copy, so you can compare both backgrounds before pasting anything.

The Tailwind version

Tailwind's arbitrary values can hold the same declarations. Underscores stand in for spaces, and the tool writes the whole class string for you:

<button type="button" class="inline-flex items-center justify-center leading-none font-semibold cursor-pointer px-[30px] py-[14px] text-[16px] rounded-[12px] border-[2px] border-transparent text-[#161616] bg-[#c4c4c0] transition-[background-position,box-shadow,filter] duration-[600ms] motion-reduce:transition-none active:brightness-[0.96] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[3px] focus-visible:outline-[#030303]">
  Book a call
</button>

That's a shortened example showing the structure. The full output also includes the gradient, size, position, clip and shadow utilities, so copy it from the tool rather than writing the arbitrary values by hand. motion-reduce:transition-none is Tailwind's version of the reduced-motion media query.

CSS or PNG?

  • CSS is resolution-independent, tiny and easy to edit later. Use it for real buttons on a page.
  • PNG is a fixed image. The generator downloads 1920×1080 for a wide hero or wallpaper, and 1000×1500 for Pinterest-style pins. Use it where you can't set CSS, such as slides or social graphics. A PNG of a button isn't clickable, so don't use it as the real button.

Everything runs in your browser. Nothing is uploaded, and there's no sign-up. Copy link gives you a URL that restores the same settings, handy for sharing with a client.

Plain HTML

Paste the rule into your stylesheet and add the class. This is the shape of the HTML the generator outputs:

<style>
  .chrome-btn { /* the rules from the generator */ }
</style>
<button type="button" class="chrome-btn">Get started</button>

Webflow

Add an Embed element with the CSS inside a <style> tag, then give your Button the class chrome-btn. More on the Webflow effects page.

Framer

Paste the CSS in a <style> tag under Site Settings → Custom Code, or drop the HTML output into an Embed. See Framer effects.

WordPress and Shopify

  • WordPress: paste the CSS under Appearance → Customize → Additional CSS, and add chrome-btn as the Button block's Additional CSS class.
  • Shopify: paste the CSS into base.css, or into a section's {% style %} block, and add the class to the button in your theme.

React and Tailwind

Paste the CSS into a stylesheet and use the class, or use the Tailwind classes straight on the element:

<button type="button" className="chrome-btn">
  Get started
</button>

See React effects for more.

Performance

Static CSS is cheap. It's text, with no script and no image request. The only animation is the background-position slide on hover, and it's turned off for visitors who prefer reduced motion.

When you need it to move

This technique is static. A gradient is the same picture of a reflection wherever the button sits and whatever the pointer does. Only the highlight moves, on hover. For most buttons that's enough.

For metal that reacts to the pointer, you need a shader. Liquid Metal Buttons draws an animated WebGL metal surface on real buttons, for $12 one-time. The step-by-step is in Liquid Metal Button Effect for Webflow, Framer and Any Site. If a still button does the job, stay with CSS. It's lighter and has nothing to load.

See it in context

The free chrome button generator lets you try finishes, light angle, shine, rim and highlight, and see the CSS change live. It also makes metallic headline text with the same gradient. When you want the metal to respond to the pointer, step up to Liquid Metal Buttons, and for the rest of the catalog see /effects.

Pricing

The generator is free. Liquid Metal Buttons, the animated WebGL version, is $12 one-time. The full catalog is available through the All-Access Pass for $49.

Pick a finish, test your label contrast, and keep the CSS if a still button does the job.