Buttons✨ Premium

RGB Split

On hover, two ghosts of the label — red shifted 2 px left, cyan 2 px right — appear at once and swap sides once in 300 ms, then stay put — pure CSS, on a midnight-blue button.

CSSHoverRGB

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. Buttons has 27 effects, including 2 free. Explore the category →

3 usage examples

Listen to the album — electronic music label release — RGB Split example 1

① Listen to the album — electronic music label release

WhenDark hero of a music release: cover art, title, date, one listen button.
WhyThe red/cyan doubling has been the vocabulary of electronic music covers and visuals since the 2010s; the effect stays sober at rest and only reveals itself on the intent to listen.
SettingsOffset raised to ±3px, 16 px uppercase text with letter-spacing, .4s animation, rgba(255,255,255,.35) border for findability.
Play — retro or arcade game card — RGB Split example 2

② Play — retro or arcade game card

WhenGame card in a library: pixel-art visual, title, year, one launch button.
WhyChromatic aberration mimics CRT screens: in 300 ms the text seems to resync like a tube image settling. A single hover is enough to evoke the era.
SettingsMonospace font, border-radius: 6px, ±2px offset kept, #12122a background to stand out from the card.
Try again — server error page — RGB Split example 3

③ Try again — server error page

When500 page or offline screen: error code, one sentence, one reload button.
WhyThe doubling signal tells the outage story without an image; the single color swap on hover gives the button a “circuit coming back on” feel that suits a retry.
Settings±2px offset, .3s animation, #f43f5e and #22d3ee colors (less saturated than red/#0ff), .35 border.

How it works

At rest, .btn-rgb-split is a sober button: #1a1a2e (midnight blue) background, white text, border: 1px solid rgba(255,255,255,.2), no shadow. No transition is declared: everything that follows appears and disappears instantly.

On :hover, text-shadow: -2px 0 red, 2px 0 #0ff lays two copies of the text behind the glyphs: a red one (#ff0000) shifted 2 px left, a cyan one shifted 2 px right. White in the middle, red left, cyan right: it's the channel misregistration of a badly aligned image — the “chromatic aberration” of the name.

At the same time rgbShift starts, .3s ease, a single iteration: at 0% and 100% the ghosts are in place (-2px / 2px), at 50% they have swapped sides (2px / -2px). Measured in Chromium: at 80 ms the red has already crossed to the right (+1.4 px), at 150 ms it's at +1.9 px, at 220 ms it's coming back (−1.4 px). So the ghosts cross the text once, in 300 ms, then the static :hover declaration holds them at ±2 px as long as the mouse stays.

On hover out, both shadows vanish with no fade, since there is no transition. The animation only replays on a new hover. Nothing moves at rest, nothing on press (:active isn't defined): it's a strictly hover-driven, lightweight effect — two blur-free text shadows, no layout property.

Accessibility

  • Text contrast: white on #1a1a2e = 17.1:1, AAA. The ghosts are added behind the glyphs without covering them; at 2 px, the red (4.3:1 on the background) and cyan (13.6:1) visually thicken the letters more than they blur them — fine for a short label at weight 600, avoid below 14 px.
  • Finding the button (WCAG 1.4.11, 3:1 threshold for a component's boundary): the #1a1a2e face on the catalog's #0a0a0f background contrasts at only 1.16:1, and the rgba(255,255,255,.2) border (#484859 once composited) at 2.2:1. A low-vision user can hardly tell where the button ends. Raise the border to rgba(255,255,255,.35) (3.7:1) or lighten the face.
  • prefers-reduced-motion not handled: the only movement is the 300 ms swap, once per hover. Add @media (prefers-reduced-motion: reduce) { .btn-rgb-split:hover { animation: none } } — the static ghosts remain, without the crossing.
  • Keyboard: no :hover for Tab navigation. Duplicate the rule under .btn-rgb-split:focus-visible (shadows and animation); the native outline is preserved and reads well on midnight blue.
  • Touch: a mouse-only effect; on iOS the ghosts stay displayed after a tap until the next touch (@media (hover: hover)). Target ≈ 52 px tall, above the 44 px minimum.

Browser compatibility

Requires multi-shadow text-shadow and unprefixed CSS animations — every browser since 2015. No JavaScript, zero dependencies.

Chrome 43+✓ Full
Firefox 16+✓ Full
Safari 9+✓ Full
Edge 12+✓ Full
Mobile iOS✓ Static (no hover)
Android Chrome✓ Static (no hover)

Without CSS animations, both ghosts appear on hover at their final position (red left, cyan right) without the 300 ms swap: the aberration is there, motionless. Without text-shadow, the button remains an ordinary midnight-blue button.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
text-shadow offset (CSS — :hover and @keyframes rgbShift, 4 occurrences) −2px / 2px Aberration amplitude. ±1px = barely visible shiver; ±4px = frankly tripled text, readable only on a short label. Change all four values together.
Ghost colors (CSS — red / #0ff) red / #0ff Red and cyan are complementary: overlaid on white they give white back, hence the “channels” effect. #f0f / #0f0 (magenta/green) is the other classic pair.
animation-duration (CSS — :hover) .3s Length of the side swap. .15s = snap; .6s = visible glide of the ghosts through the text.
animation-iteration-count (CSS — :hover) 1 Number of swaps per hover. infinite keeps the ghosts oscillating while the mouse stays — more “glitch”, more tiring.
border (CSS — .btn-rgb-split) 1px solid rgba(255,255,255,.2) Button outline, the only landmark on a dark background. .35 reaches 3:1 on #0a0a0f; .5 is crisp.
background (CSS — .btn-rgb-split) #1a1a2e Midnight-blue face. Any dark color works; the red and cyan ghosts lose their effect on a light background (cyan disappears on white).
transition (CSS — to add) none transition: text-shadow .2s fades the ghosts in and out instead of snapping; the swap animation keeps control during its 300 ms.

FAQ

Because the code declares no transition: on hover, text-shadow goes from none to its two shadows instantly and the animation takes over for the swap; on hover out, the shadows are removed the same way. Add transition: text-shadow .2s on .btn-rgb-split: appearance and disappearance fade, and since a running animation takes precedence over the transition, the 300 ms swap stays intact.
Replace the single iteration with infinite: .btn-rgb-split:hover { animation: rgbShift .3s ease infinite }. The ghosts then oscillate from −2 to +2 px three times a second. It's markedly more aggressive: keep it for a short label, slow it to .6s, and keep the prefers-reduced-motion rule that cuts the animation.
Yes: text-shadow and the animation don't depend on the tag. On larger text, scale the offset with the font size — 0.06em instead of 2px gives 2 px at 32 px and 4 px at 64 px — and trigger it on hover of the parent block or permanently. On a long paragraph, aberration hurts reading: keep it for headings and labels.