Gradient Wave
A 4-color diagonal gradient pans in a smooth loop across a surface 4× wider than the container — pure CSS, zero dependencies.
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. Backgrounds has 50 effects, including 6 free. Explore the category →
3 usage examples



How it works
The technique relies on a single animated property: background-position. The gradient is declared as linear-gradient(-45deg, …) — bottom-left to top-right diagonal — with four color stops (indigo #6366f1, violet #8b5cf6, fuchsia #d946ef, cyan #06b6d4). A background-size: 400% 400% expands the painted surface to 4× the element's width and height: the browser has a large palette to pan across.
The @keyframes gradientWave shifts that surface from 0 50% to 100% 50% and back in 15 seconds. The Y axis stays fixed at 50%: only the X axis oscillates, keeping the diagonal centered vertically and preventing any perceptible drift. The ease timing function adds a natural acceleration at each end of the swing.
Because the gradient is diagonal (−45°) and the panned surface covers ¾ of the total width (from 0% to 100% of a 4× wider background), each hue sweeps diagonally across the screen in turn, creating the impression of a continuous color wave. Changing the angle (135deg reverses direction), the number of stops, or the background-size radically alters the wave's amplitude and rhythm.
The animation is handled entirely by the browser's compositor thread: no JavaScript is required, no reflow is triggered. The .bg-wave element accepts overlay content — just add position: relative via your CSS to position children absolutely on top of the animated background.
Accessibility
- prefers-reduced-motion not implemented: no
@media (prefers-reduced-motion: reduce)rule is present in the provided CSS — the animation runs on all systems, including those requesting less motion. Add it yourself:@media (prefers-reduced-motion: reduce) { .bg-wave { animation: none; } }. - The
.bg-waveelement is purely decorative in most use cases: addaria-hidden="true"if none of its children are intended for screen readers. - Overlay text and contrast: indigo/violet tones (
#6366f1,#8b5cf6) yield white-text contrast ≈ 4.6:1 during the cool phase — but the light cyan (#06b6d4, luminance ≈ 52%) drops below 3:1. A semi-transparent scrim behind the text ensures WCAG AA compliance regardless of animation phase. - No native interactivity: no focusable elements in the effect, no keyboard handling required for the background alone.
- If
.bg-wavecovers the main region of the page (hero), consider addingrole="region"and anaria-labelfor screen readers.
Browser compatibility
CSS linear-gradient, background-size, and @keyframes are supported in all modern browsers since 2013. No vendor prefixes required.
If CSS animations are disabled or unsupported, <code>.bg-wave</code> displays the gradient statically at position <code>0 50%</code> (indigo/violet dominant). No JS errors, no network resources required.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="bg-wave">
<!-- Optional overlay content -->
<!-- Add position:relative to the .bg-wave selector in your CSS -->
<!-- to position children absolutely on top of the animated background. -->
<span class="bg-label">Your centered text</span>
</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 |
|---|---|---|
| animation-duration on .bg-wave | 15s | Full cycle speed. 8 s = dynamic, 25 s = calm and near-static while reading. |
| Angle in linear-gradient | -45deg | Diagonal direction. 135deg reverses the panning direction; 90deg produces a pure horizontal wave. |
| Color stops in linear-gradient | #6366f1, #8b5cf6, #d946ef, #06b6d4 | Wave palette. 3 stops = softer transitions, 5+ = kaleidoscope effect. Paste your brand colors here. |
| background-size on .bg-wave | 400% 400% | Panning amplitude. 200% = short pronounced wave, 600% = very gradual shift. |
| animation-timing-function on .bg-wave | ease | linear removes acceleration for a steady scroll; ease-in-out accentuates pauses at the extremes. |
| background-position Y in keyframes | 50% | Vertical offset of the wave. 0% or 100% reveals the top/bottom edges of the extended gradient — adds a complementary vertical shift. |
FAQ
@keyframes gradientWave block and the .bg-wave rule into your stylesheet, add the class to your div, and you're done. Compatible with all frameworks (React, Vue, Svelte, Angular) and static site generators.position: relative to .bg-wave, then place your children as position: absolute or in normal flow. To guarantee contrast at every animation phase, add a scrim (e.g. background: linear-gradient(to bottom, rgba(0,0,0,0.55), rgba(0,0,0,0.20)) as position: absolute; inset: 0; z-index: 1) and put text at z-index: 2.background-position on a CSS gradient only triggers the compositor step — no reflow, no DOM repaint. GPU load is negligible even on mobile. For users with Reduce Motion enabled, add @media (prefers-reduced-motion: reduce) { .bg-wave { animation: none; } }: the gradient remains visible, static.