Shine Effect
Semi-transparent shine sweeping diagonally across the card on hover — pure CSS, ::before pseudo-element and translateX transition, zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Cards has 41 effects, including 6 free. Explore the category →
3 usage examples



How it works
The effect relies entirely on the ::before pseudo-element of .card-shine. That pseudo-element is oversized to 200% × 200% of the card (top: -50%; left: -50%; width: 200%; height: 200%) and carries a linear-gradient(to right, transparent 0, rgba(255,255,255,.1) 50%, transparent 100%) — a white central band that fades on both sides. Rotated 45° by rotate(45deg), this horizontal gradient becomes a diagonal band crossing the card corner to corner at any card size.
overflow: hidden on .card-shine acts as a clipping window: the pseudo-element extends well beyond the card's edges, but only what falls within its bounds is visible. At rest, transform: rotate(45deg) translateX(-100%) places the pseudo-element entirely off-screen to the left — translateX applies in the rotated coordinate frame, i.e. along the diagonal axis. On hover, transform: rotate(45deg) translateX(100%) shifts it to the other side; transition: transform .6s animates this travel and produces the luminous sweep.
Three CSS custom properties (--bg-card, --border, --radius-xl) centralise card theming. No external libraries, no scripts: adding the card-shine class to any element with position: relative and overflow: hidden activates the effect instantly, with no configuration.
Accessibility
- prefers-reduced-motion absent: no
@media (prefers-reduced-motion: reduce)block exists in the provided code — the animation fires even when the OS signals a preference to reduce motion. For WCAG 2.3 compliance, add@media (prefers-reduced-motion: reduce) { .card-shine::before { transition: none; } }. - The effect is triggered exclusively by
:hover— on touch screens (iOS, Android) the event does not fire on tap; the card displays in its static state with no errors. - The
::beforepseudo-element is purely decorative: it is absent from the accessibility tree and invisible to screen readers. - The card structure defines no ARIA attributes by default — semantics (role, label, state) are carried by the content you place inside.
- Contrast: the white shine at 10% opacity is negligible against underlying text. If you raise opacity above 25%, verify the WCAG AA contrast ratio during the sweep.
Browser compatibility
Requires only CSS Transitions and pseudo-elements — supported everywhere for many years. Zero external dependencies.
Without :hover support (touch devices) or without CSS Transitions, the card displays normally in its static state — no JS errors, no hidden content.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="card-demo card-shine">
<!-- Your content: heading, price, list, image… -->
<h3>Title</h3>
<p>Short description</p>
<button>Action →</button>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| --bg-card | #12121a | Card background color — replace with your brand color or set a gradient directly via background on .card-shine. |
| --border | rgba(255,255,255,0.08) | Card border color and opacity — raise to rgba(255,255,255,0.20) for a more visible edge, or switch to a brand color for a colored frame. |
| --radius-xl | 1rem | Corner border radius — 0 for sharp edges, 1.5rem for very rounded cards, 50% for a circle (equal width and height). |
| rgba(255,255,255,.1) in ::before | 0.1 | Shine brightness: .05 = very subtle, .2 = prominent, .35 = vivid. Check text contrast above 0.25. |
| rotate(45deg) in transform | 45deg | Shine angle: 30deg for a gentler sweep, 60deg for steeper, 0deg for a purely left-to-right horizontal wipe. |
| transition: transform .6s | .6s | Sweep duration: .3s = crisp flash, 1s = slow cinematic glide. Append ease-out for a natural deceleration at the end. |
FAQ
card-demo and card-shine classes to your element and copy the CSS. No dependencies, no scripts. Works with Angular, React, Vue, Svelte: apply the classes to the container element in your template.:hover does not fire on tap on iOS and Android. The card displays in its static state, with no errors. For touch feedback, combine with an :active state or a :focus-triggered animation.::before pseudo-element with transform creates its own stacking context and paints above normal-flow content. At 10% opacity this is visually negligible. To keep it behind the text, add z-index: -1 to .card-shine::before and set an explicit non-auto z-index on .card-shine.