The Missing Bit

Mitigating CSS gradient banding

While working on a design that included a gradient, I noticed banding when the gradient was rendered by the browser.

The following image shows the issue and in comparison the technique I used to workaround the problem.

{{< figure src="/images/2016-09-16-css-banding.png" title="CSS banding" >}}

  1. Augmented contrast of stepped CSS gradient.
  2. Stepped CSS gradient (the result we actually want).
  3. Naive CSS gradient
  4. Augmented contrast of the CSS gradient (to highlight the banding issue).

What are we seeing here? Simply put, the browser cannot render a gradient properly. As I cannot fix the browsers (seen into Safari, Chrome and Firefox), I tried to find a workaround.

The workaround I found is what I call "stepped gradient". Basically, instead of having one gradient from color A to B, I to a serie of gradients from A to A1, then A1 to A2… until An to B. Where Ax is closer to B each time.

The SASS code to achieve this is below.

$g: transparent;
$steps: 10;
@for $i from 1 to $steps {
  $g: append($g, fade-out($bg-color, 1 / $i) percentage($i / $steps), comma);
  $g: append($g, fade-out($bg-color, 1 / $i) percentage(($i + 0.6) / $steps), comma);
}
$g: append($g, $bg-color);
background: linear-gradient(to bottom, $g);