I wanted a slow, living gradient behind a hero, the kind that feels expensive. My first attempts animated background-position on a huge gradient and it hitched badly on scroll and cooked laptop fans, because it forces repaint every frame.
The fix was to constrain the model to GPU-friendly properties only (transform/opacity), animate a couple of large blurred radial "blobs" on transforms behind a overflow:hidden container, and require it to explain why each animated property avoids layout/paint. Adding a reduced-motion still frame made it shippable.
Gemini did well once the constraints were explicit. Prompt below. Anyone gotten this smooth without the blurred-blob trick?
Create a hero section with an animated gradient background as a single HTML file with inline CSS, no JS, no libraries. Mood: {MOOD e.g. calm, dawn}. Accent hues: {HUE_A}, {HUE_B}.
PERFORMANCE CONSTRAINTS (strict):
- Animate ONLY transform and opacity. Do NOT animate background-position, background-size, filter, or box-shadow (they trigger paint/layout).
- Technique: 2-3 large radial-gradient 'blobs' as absolutely-positioned divs inside an overflow:hidden hero; each blob is blurred once (static filter: blur, not animated) and drifts via translate + subtle scale on different, non-synchronized durations (20-40s) so the motion never obviously loops.
- Add will-change: transform on the blobs; keep total animated nodes <= 3.
- The foreground text sits on a container with its own solid/low-opacity backdrop for contrast; verify text contrast >= 4.5:1 against the busiest point of the gradient.
- prefers-reduced-motion: reduce -> freeze blobs to a pleasant static composition (no animation), still on-brand.
Before the code, in 3 bullets explain why each animated property stays on the compositor and off the main thread. Then the code with real hero copy.