Rainbow Shimmer
A 280×296 px skeleton card, 7 bones (48×48 px avatar, title/subtitle, 120 px image zone, 3 text lines), each swept by a 7-band rainbow shimmer (red→violet, 0.15 opacity) moving left to right every 2.5 s. Pure CSS, no 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. Loaders has 29 effects, including 4 free. Explore the category →
3 usage examples



How it works
The .rainbow-skel card (280 px wide, 20 px padding, rgba(255,255,255,.03) background, rgba(255,255,255,.06) border, 16 px corners) holds 7 bones: a 48×48 px avatar circle (.rainbow-bone-circle), a title bar (14 px tall, 65% of the right column) and a subtitle bar (10 px, 45%), a 120 px image zone, and three 10 px text lines. All bones carry background: rgba(255,255,255,.06) — the content silhouette on a dark background — and overflow: hidden, which clips the shimmer pseudo-element to each bone's edges.
The shimmer is a ::after set to position: absolute; inset: 0 carrying a linear-gradient(90deg, ...) in seven colored bands — red rgba(255,50,50,.15) at 15%, orange at 25%, yellow at 35%, green at 45%, blue rgba(0,180,255,.18) at 55%, indigo at 65%, violet at 75% — on a transparent base, with background-size: 300% 100%: the gradient is three times the bone's width. The rainbowSlide animation moves background-position from -300% 0 to 300% 0 in 2.5 s ease-in-out infinite — a total sweep of 600%. The visible window (100% of the bone) passes through all seven hues during each cycle. Peak opacity is 0.18 (blue) over the rgba(255,255,255,.06) bone base: the gradient is intentionally translucent to remain subtle on a dark background.
Four start delays are applied through nth-child selectors: .rainbow-skel-title::after (1st child of its parent) → 0 s; .rainbow-skel-subtitle::after (2nd) → 0.1 s; .rainbow-skel-img::after (2nd child of .rainbow-skel) → 0.1 s; 1st line (3rd child) → 0.2 s. The 2nd and 3rd lines (4th and 5th children) match no rule and revert to the default 0 s delay, running in phase with the avatar and title. Additionally, .rainbow-skel-line:nth-child(2) { width: 93% } looks for a line that is the 2nd child of its parent — that role belongs to .rainbow-skel-img, not a text line: the rule matches nothing (measured: lines 1 and 2 at 238 px = 100%, only line 3 reaches 64% via :last-child). There is no JavaScript; the js field of the sold code is empty.
Accessibility
- prefers-reduced-motion not handled: measured — no
@media (prefers-reduced-motion)rule is present; under that preference therainbowSlideanimation keeps running. Add:@media (prefers-reduced-motion: reduce) { .rainbow-bone::after, .rainbow-bone-circle::after { animation: none } }. - The sold HTML contains no ARIA attributes for a loading indicator. The
.rainbow-skelcontainer should carryrole="status",aria-busy="true"andaria-label="Loading"(or equivalent) during the wait; setaria-busytofalseand remove the skeleton once the real content appears. - The 7 empty bones should not be visited by screen readers. Add
aria-hidden="true"to.rainbow-skel(without it, a screen reader would enumerate seven silent elements). - Contrast: the bones (
rgba(255,255,255,.06)≈ #111) on the#0a0a0fbackground measure ~1.0:1 — intentional, they are decorative shapes, not text. The rainbow shimmer (graphical element, 3:1 threshold) is too translucent to measure meaningfully. On a white background without the sold CSS's.demo-preview { background: #0a0a0f }, the bones vanish into the white.
Browser compatibility
Requires the inset shorthand (top/right/bottom/left), linear-gradient, animation on pseudo-elements, background-size and animated background-position. No custom properties, no clip-path, no mix-blend-mode.
Without inset (pre-2021 browsers), the ::after pseudo-element is not positioned over the bone: the rainbow shimmer disappears but the bones themselves remain visible as a static skeleton. Without animation on pseudo-elements (IE), the skeleton is fully static.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="rainbow-skel">
<div class="rainbow-skel-header">
<div class="rainbow-bone-circle rainbow-skel-avatar"></div>
<div style="flex:1">
<div class="rainbow-bone rainbow-skel-title"></div>
<div class="rainbow-bone rainbow-skel-subtitle"></div>
</div>
</div>
<div class="rainbow-bone rainbow-skel-img"></div>
<!-- 3 lines total -->
<div class="rainbow-bone rainbow-skel-line"></div>
<div class="rainbow-bone rainbow-skel-line"></div>
<div class="rainbow-bone rainbow-skel-line"></div>
</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 |
|---|---|---|
Cycle duration (CSS — animation: 2.5s) |
2.5 s ease-in-out infinite | Speed of the rainbow sweep on each bone. 1.5s = lively shimmer, sense of active loading; 4s = slow wave, more contemplative feel. Change the value in the ::after animation declaration. |
Band opacity (CSS — .15 / .18) |
0.15 for six bands, 0.18 for blue | Visible intensity of the rainbow gradient. On a dark #0a0a0f background, .30–.40 gives a more pronounced shimmer; on a light background, raise to .50–.60 and also raise the bone base to rgba(255,255,255,.10). |
Bone base color (CSS — .rainbow-bone { background: rgba(255,255,255,.06) }) |
rgba(255,255,255,0.06) | Color and opacity of the bone silhouette at rest. On a light background, use rgba(0,0,0,.08) to keep the bones visible; on a colored background, match the hue for coherence. |
Card width (CSS — .rainbow-skel { width: 280px }) |
280 px | Fixed width of the skeleton. Switch to 100% to fill a fluid container; the percentage-width bones (65%, 45%) follow automatically. |
Image zone height (CSS — .rainbow-skel-img { height: 120px }) |
120 px | Adapts the skeleton to the actual proportion of the expected image: 80px for a square thumbnail, 200px for a wide landscape, or use aspect-ratio: 16/9 for video content. |
Stagger delays (CSS — animation-delay: 0s / .1s / .2s) |
0 s, 0.1 s, 0.1 s, 0.2 s (the 2 last lines stay at 0 s — see measured defect) | For a clean cascade across all 7 bones, replace the nth-child rules with explicit selectors: .rainbow-skel > .rainbow-bone:nth-child(3)::after { animation-delay: .2s }, :nth-child(4)::after { animation-delay: .3s }, :nth-child(5)::after { animation-delay: .4s }. |
Gradient width (CSS — background-size: 300% 100% + keyframes -300%→300%) |
300% (gradient 3× wide), 600% sweep | A wider gradient (400%) stretches the bands and softens transitions. Change all three values together: background-size and both background-position values in the keyframes. |
FAQ
.rainbow-skel-line:nth-child(2) { width: 93% } targets an element that is both a .rainbow-skel-line and the 2nd child of its parent. In the sold HTML, the 2nd child of .rainbow-skel is .rainbow-skel-img, not a text line — the lines sit at positions 3, 4, and 5. The rule matches nothing (measured: lines 1 and 2 at 238 px = 100%, line 3 at 152 px = 64% via :last-child). To fix it, target by position inside .rainbow-skel: .rainbow-skel > .rainbow-bone:nth-child(4) { width: 93% } gives 93% to the 2nd line without touching the image zone.scaleY oscillation (1→1.02→0.98→1 over 2.2 s) giving the bones a gentle breathing movement; Rainbow Shimmer moves strictly horizontally over 2.5 s. Use Wave Shimmer for a sober interface; Rainbow Shimmer when the palette of the incoming content justifies a colored signal.rgba(255,255,255,.06) — on white, the bones become nearly invisible. Replace the base with rgba(0,0,0,.08) to make them visible on a light surface. Then raise the rainbow band opacities to .40–.50 so the gradient reads over the darker bones.