How can I prevent CSS gradient banding?
Asked Answered
B

8

57

I started using CSS gradients, rather than actual images, for two reasons: first, the CSS gradient definitely loads faster than an image, and second, they aren't supposed to show banding, like so many raster graphics. I started testing my site on various screens recently, and on larger ones (24+ inches), the CSS linear gradient which constitutes my site's background shows very visible banding. As a provisional fix, I've overlaid the gradient with a small, repeating, transparent PNG image of noise, which helps a little. Is there any other way to fix this banding issue?

Berceuse answered 26/7, 2012 at 9:32 Comment(3)
1) It's depending on the browser's rendering. 2) It's depending on your monitor.Mediatory
I've decided to use a solution based on @Michael Giovanni Pumo's answer: make a 1px high gradient in Photoshop, use blur, grain, and other dither methods to remove banding, and have it repeat-x.Berceuse
Tip: Whatever technique you end up using make sure you're aware about the infamous iOS rendering 'quirk' where fading to transparent actually always fades to transparent black. betterprogramming.pub/… This longstanding issue can really make gradients look bad and any clever fix to correct banding that doesn't take this into account is a waste of time if you have to target iOS usersOrbital
B
24

I know you won't like the sound of this, but the only real way right now to get a consistent cross-browser aesthetic in this case, is to use a repeating image.

If it's a simple linear gradient, then you only need it to be 1px wide and as high as the gradient, then make the background colour of the page as the final colour of the gradient so it runs smoothly. This will keep file size tiny.

If you want to reduce gradient bands in your image, use a PNG (not transparency) as I find these to be better suited than JPG's for this purpose.

In Adobe Fireworks, I would export this as a PNG-24.

Good luck.

http://codepen.io/anon/pen/JdEjWm

#gradient {
  position: absolute;
  width: 100%;
  height: 100%;
  background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(black), to(white));
  background: -webkit-linear-gradient(top, black, white);
  background: -moz-linear-gradient(top, black, white);
  background: -ms-linear-gradient(top, black, white);
  background: -o-linear-gradient(top, black, white);
  background: linear-gradient(top, black, white);
}
Bohlin answered 26/7, 2012 at 10:17 Comment(0)
A
24

You can yield slightly better results by making your gradient go from the first colour to transparent, with a background-color underneath for your second colour. I'd also recommend playing around with background-size for large gradients that stretch across the screen, so the gradient doesn't actually fill the whole screen.

Awoke answered 5/3, 2013 at 17:8 Comment(3)
I can confirm that overlaying gradient over background-color actually works better. Also try swapping background-color and gradient color because one of the options seems to always be looking better (webkit/blink)Oblation
I never thought about overlapping 2 gradients with a transparent side on each side. I will definitely remember that for when I need it!Clementinaclementine
No, this method actually made the banding significantly worse.Everyday
B
5

I made a "scatter.png" to put with my gradient. Like this:

  1. Open gimp
  2. 100x100 image
  3. Add alpha channel
  4. Filters -> Noise -> Hurl... Accept defaults
  5. Set opactity to 5%
  6. Save and then add to gradient.

    background: url('/img/scatter.png'), linear-gradient(50deg,#d00 0,#300 100%);
    

It's a subtle effect on a subtle effect.

Braden answered 23/9, 2016 at 13:30 Comment(0)
E
4

I know this issue is long solved, but for others experiencing banding and looking for a solution, a very easy fix for me was just simplifying the colours I included in my gradient. For example:

This gradient produces banding:

background-image: linear-gradient(-155deg, #202020 0%, #1D1D1D 20%,
#1A1A1A 40%, #171717 60%, #141414 80%, #101010 100%);

This gradient does not, and looks much the same:

background-image: linear-gradient(-155deg, #202020 0%, #101010 100%);
Everyway answered 15/1, 2018 at 4:18 Comment(0)
A
3

For a pure CSS answer you can use a blur filter to add blur to the css gradient and alleviate the banding. It can mean some rebuilding of the hierarchy to not blur the content and you need to hide the overflow to get crisp edges. Works really good on an animating background where the banding issue can be especially dire.

.blur{
  overflow:hidden;
  filter: blur(8px);
}
Alarise answered 1/9, 2017 at 14:33 Comment(1)
Tried the blur technique. The performance was extremely poor. One or two blur layers did improve the quality but at an extreme performance cost. 10 layers with 100px blur took my eeepc several minutes to display.Streptomycin
M
2

There's not really any method to remove the banding. CSS gradients are at the mercy of the various rendering engines of the browsers. Some browsers simply render better than others. The best you can do is short areas to cover and larger color ranges to increase the gradient steps.... Then wait for browser rending to improve.

Mumford answered 26/7, 2012 at 9:35 Comment(0)
C
1

I know this is a bit very late, but I discovered a trick that works. For anyone having that rough edge at meet point of the colors. This removes it.

.gradient {
  background: linear-gradient(
    173deg,
    rgba(0, 132, 255, 1) 50%,
    rgba(255, 255, 255, 1) 50.5%
  );
}
Costrel answered 26/7, 2020 at 19:30 Comment(0)
G
-4

Add a min-height.

#gradient {
  min-height: 100vh;
  background: linear-gradient(black, white);
}

you can also set background-repeat to no-repeat but shouldn't be necessary.

#gradient {
  min-height: 100vh;
  background: linear-gradient(black, white);
  background-repeat: no-repeat;
}
Gavingavini answered 14/3, 2021 at 15:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.