Chrome Reflection
Polished-metal pill button: on hover or focus, a slanted white shine sweeps across its upper half, then sweeps back when you leave it.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Distortion has 31 effects, including 5 free. Explore the category →
3 usage examples



How it works
The .chm-btn is a real <button>. Its chrome look comes from a vertical gradient of white, light grey, mid grey in the middle, then light grey and white, finished with three shadows: a drop shadow under the button, a light line at the top and a dark line at the bottom, inside. A plain #d4d4d4 colour is declared under the gradient in case it doesn't render.
The shine is the ::before pseudo-element: a band as wide as the button and half as tall, in a transparent, 80% white, transparent gradient, slanted by 25°. It waits outside the button, on the left (left: -100%). On hover or focus, it moves to left: 200% in 0.5 s (--chm-speed): you see it sweep the top of the button once.
It is a transition, not a loop: when hover or focus ends, the shine travels back from right to left. While the mouse stays on it, nothing moves. Overflow is clipped by overflow: hidden.
Accessibility
- Real button:
<button type="button">with its real text, activated with Enter and Space, announced as a button by screen readers. - Keyboard: focus triggers the same shine pass as hover, and an outline (
--chm-ring) appears when focus comes from the keyboard. In Safari, the Tab key doesn't stop on buttons unless the “Press Tab to highlight each item” option is on (measured in WebKit); that's a browser setting, not the effect. - Touch: tapping the button triggers the shine pass (measured in Chromium, Firefox and WebKit with an emulated touch screen).
- Reduced motion: with
prefers-reduced-motion: reduce, the shine no longer slides; on hover or focus it shows still over the top half of the button, at 55% opacity. - Contrast: the
#1a1a1atext sits in the middle of the button, where the metal is darkest (#737373): the ratio there is 3.7:1. That is enough for the bundled 1.25rem bold text (large text under WCAG, 3:1 threshold), not for smaller text: keep at least 18.7 px bold, or edit the gradient to lighten its middle.
Browser compatibility
CSS only, no JavaScript. Measured in Chromium 151, Firefox 153 and Playwright's WebKit 26.5: 0 errors, two independent copies, hover, focus, touch, 390 px and reduced motion. The copy-paste checker no longer reports “invisible text” since the fallback colour was added. Minimum versions per @mdn/browser-compat-data: CSS variables set the floor (Chrome 49, Firefox 31, Safari 9.1).
Without :focus-visible (before Safari 15.4 and Chrome 86), the focus outline doesn't show; the shine still passes on focus.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0264-root"><button class="chm-btn" type="button">CHROME</button></div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
--chm-pad |
20px 50px |
Button padding (vertical, then horizontal). |
--chm-font |
1.25rem |
Text size. |
--chm-radius |
50px |
Corner rounding: 50px gives a pill, 12px a rectangular button. |
--chm-speed |
.5s |
Duration of one shine pass, there and back. |
--chm-text |
#1a1a1a |
Text colour; stay with a very dark shade to keep contrast on the metal. |
--chm-ring |
#e5e5e5 |
Outline colour on keyboard focus. |
--chm-bg and --chm-min-h |
#0a0a0f and 300px |
Root background and minimum height; transparent and 0 to place the button in your page. |
FAQ
.chm-btn has its own shine. The root is a centred flex container; change its layout (grid, column) in your CSS if needed.left property returns to its starting value with the same duration. For a single pass, set transition: none on .chm-btn::before outside hover and keep the transition in the :hover rule.chm-btn class works on an <a href>, since the shine also follows :hover and :focus. Add display: inline-block and text-decoration: none to the link.