CSS and web

CSS gradient performance: do gradients slow a site down?

A static CSS gradient is almost free. The costs come from what people do with gradients: huge blurs, backgrounds that repaint on scroll, and animations that never stop. Here is how to tell the difference.

GradientlyVerified Gradiently account··6 min read
Cover: Burnt Mist · GR·3M7T·BR

The short version

  • A static CSS gradient costs almost nothing to load, because it is a line of text rather than a file to download and decode.
  • Gradients cost paint time, which grows with the area painted and the number of layers, but a static gradient is painted once and then reused.
  • The real performance risks are large blur filters, backgrounds that repaint while scrolling, and gradient animations that repaint every frame.
  • Animating transform or opacity on a gradient layer is usually far cheaper than animating background-position or colour stops.
  • The only reliable answer for a specific page is to measure it, with paint flashing and a Performance recording in browser developer tools.
On this page

Good CSS gradient performance is the normal case: a static gradient does not slow a website down in any way you could notice. It is a line of text, so there is nothing to download, nothing to decode and nothing to wait for. Gradients cost a little paint time, like every other colour on the page. Slow pages come from a few specific patterns built on top of gradients: large blurs, repaints while scrolling and animations that repaint every frame. This guide shows which is which and how to check your own page.

Loading: gradients versus images

background: linear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6); is 67 characters. It arrives inside your stylesheet, needs no extra request, and renders sharp at any size and pixel density. An image background needs its own request, has to be decoded before it can be drawn, and has to be large enough for big, high-density screens.

67 characters of CSSlinear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6)
This whole background, at any size, costs less than a sentence of text to load.
BackgroundDownloadDecoded memory at 1920×1080
CSS gradientA few dozen bytes in your CSSNo bitmap to keep; painted as needed
Compressed image (AVIF, WebP, JPEG)A separate file, often tens to hundreds of kilobytesAbout 8.3 MB (width × height × 4 bytes)
Same image at 3840×2160 for sharp 4KLarger againAbout 33 MB
Decoded images are held as full bitmaps, whatever their file size. The memory figures are simple arithmetic: pixels times four bytes.

So for simple and moderately layered backgrounds, CSS wins on loading every time. Images still make sense when the background is genuinely complex, such as a painterly mesh gradient with many colour points or a photographic texture. Then the trade is file weight for visual richness, and it is often worth it.

Painting: what a gradient costs on screen

To show a gradient, the browser calculates a colour for every pixel it covers: that is painting. The work grows with the painted area, the number of stacked gradient layers and any effects on top. For a static background it happens once, and the result is reused while you scroll or interact, unless something invalidates it.

Painted once

  • A static gradient on a card or hero
  • Several layered radial glows that do not move
  • A tiled noise texture over a gradient
  • A gradient border drawn with backgrounds

Painted again and again

  • Animating background-position or colour stops
  • background-attachment: fixed while scrolling
  • backdrop-filter blur over moving content
  • An element with a gradient that resizes continuously

The real risks: blur, fixed backgrounds and animation

Large blurs. filter: blur() and backdrop-filter sample many surrounding pixels for every pixel, and the work grows with both the blur radius and the area. A blurred gradient that is painted once is usually fine. A backdrop-filter over content that scrolls underneath has to be recomputed as that content moves, which is where glassmorphism interfaces tend to stutter on modest phones.

Fixed backgrounds. background-attachment: fixed keeps a background still while the page scrolls, which can force it to repaint on every scroll step. If you want a gradient that stays put, a position: fixed element behind the content is usually cheaper, because the browser can move it as a separate layer.

Animation. Moving background-position or animating colour stops through @property repaints the element every frame. On a button that is trivial. On a full-screen hero, it is continuous work for as long as the page is open, which shows up as heat and battery drain on phones.

css
/* repaints the whole hero every frame */
.hero--costly {
  background: linear-gradient(120deg, #1e1b4b, #7c3aed, #f472b6);
  background-size: 300% 300%;
  animation: pan 12s ease-in-out infinite alternate;
}

/* the browser can usually just move a finished layer */
.hero--cheap::before {
  content: "";
  position: absolute;
  inset: -50%;
  z-index: -1;
  background: conic-gradient(#1e1b4b, #7c3aed, #f472b6, #1e1b4b);
  animation: turn 40s linear infinite;
}

@keyframes pan { to { background-position: 100% 50%; } }
@keyframes turn { to { transform: rotate(1turn); } }
Two animated heroes. The second animates transform, which browsers can usually handle on the compositor without repainting.

The CSS animated gradient guide has the full set of techniques, from cheapest to most flexible.

Layers and will-change

Promoting an element to its own compositor layer, with will-change: transform or an active transform animation, is what makes cheap animation possible. It is not free: each layer holds its own bitmap in graphics memory, roughly width × height × 4 bytes at device pixels. One oversized layer for a hero background is fine. Dozens of promoted cards, each with its own gradient layer, can use more memory than they save in paint time. Add will-change to the elements that actually animate, not as a blanket rule.

PatternBrowser workCheaper alternative
Animated background-position on a heroRepaint every frametransform on an oversized gradient layer
background-attachment: fixedRepaint while scrollingA position: fixed gradient layer behind content
backdrop-filter over scrolling contentBlur recomputed as content movesA pre-blurred static layer, or a smaller blurred area
Live SVG noise filter on a large elementFilter runs over every repainted pixelA small tiled noise image
will-change on every cardMany layers held in graphics memorywill-change only on what animates
Common gradient patterns, what they make the browser do, and the lighter way to get the same look.

How to measure gradient performance

  1. 1

    Turn on paint flashing

    In Chrome DevTools, open the Rendering panel and enable Paint flashing. Anything that flashes green while nothing should be changing is repainting.

  2. 2

    Record a Performance trace

    Record a few seconds of scrolling or idle animation in the Performance panel. Look at how much of each frame is spent in paint and whether frames are dropped.

  3. 3

    Throttle the CPU

    Use the Performance panel's CPU throttling to simulate a slower device. A hero that is smooth on a fast laptop can struggle on a mid-range phone.

  4. 4

    Check the Layers panel

    See how many compositor layers exist and how much memory they use. Unexpectedly many layers usually means will-change is overused.

  5. 5

    Test the real device

    Finish on an actual phone. Heat and battery drain from constant animation are easy to miss on a desktop.

web.dev's guide to rendering performance explains the pipeline behind these tools: style, layout, paint and composite. Knowing which stage your gradient triggers tells you whether it is cheap.

A performance checklist for gradients

  • Use CSS gradients for simple and layered backgrounds; images only when the look genuinely needs them.
  • Keep blur radii modest, and avoid backdrop-filter over large scrolling areas.
  • Replace background-attachment: fixed with a fixed-position layer.
  • Animate transform or opacity, not background-position, on large areas.
  • Slow, ambient animations can stop entirely for reduced motion users.
  • Add grain as a small tiled image, not a live SVG filter on a big element; see CSS noise texture.
  • Measure before and after with paint flashing and a Performance recording.

Questions people ask

Do CSS gradients slow down a website?

Static CSS gradients do not in any noticeable way. They need no download and are painted once. Large blurs, fixed backgrounds and constant animation are what cost performance.

Is a CSS gradient faster than a background image?

Usually yes. A gradient is a few dozen bytes of CSS with no request or decoding, while an image needs a download and is held in memory as a full bitmap.

Are animated gradients bad for performance?

Animating background-position or colour stops repaints every frame, which matters on large areas. Animating transform or opacity on a gradient layer is usually much cheaper.

Why is my blurred gradient background slow?

Blur samples many neighbouring pixels for each pixel, so cost grows with radius and area. It is worst with backdrop-filter over content that scrolls or animates.

How do I check if my gradient is repainting?

Enable Paint flashing in the Rendering panel of Chrome DevTools. Areas that keep flashing while the page is idle are repainting.

Share this guide

Written by GradientlyVerified Gradiently account

The team behind Gradiently, a design tool built around Marks: living gradients that make everything you design look like yours.

See our profile