Mixins for semi-transparent colors

One of the things I love most about Sass is its ability to calculate colors based on other colors. I often use functions like darken(), saturate(), and adjust-color() to calculate highlight colors or shadows for things like buttons.

Recently I've enjoyed using semi-transparent colors in my designs to better blend elements with their backgrounds. Sass makes it easy to create semi-transparent colors with the rgba() function:

.button {
  background: rgba(black, 0.5);
}

In CSS, rgba() takes four parameters. The first three are for red, green, and blue. The last is the alpha channel. Sass allows you to pass just two parameters. The first can be any color and the last, like the CSS version, is the alpha channel. At compile time Sass will translate the two parameter version into four.

But rgba() colors come with a price. Earlier versions of Internet Explorer can't interpret them correctly. When browsers have trouble interpreting an attribute/value pair they ignore it. This means that any element with an rgba() background will be rendered as completely transparent. You can get around this by including another color attribute with a format older browsers understand:

.button {
  background: #7f7f7f;
  background: rgba(black, 0.5);
}

If you have a color picker tool, you can grab the values of the mixed colors yourself and add the additional attribute/value pairs manually, but this can be quite tedius. Why not use the the mix() function to mix the colors for you?

.button {
  background: mix(black, white, 50%);
  background: rgba(black, 0.5);
}

But we can do better than this! Invoking some deeper magic, we can write a mixin that extracts the alpha component of a color, convert it to a percentage and use mix() to convert an rgba() color and a background color into the appropriate attribute/value pairs:

@mixin alpha-background-color($color, $background) {
  $percent: alpha($color) * 100%;
  $opaque: opacify($color, 1);
  $solid-color: mix($opaque, $background, $percent);
  background-color: $solid-color;
  background-color: $color;
}

Now we can write our code like this:

.button {
  @include alpha-background-color(rgba(black, 0.5), white);
}

Which greatly simplifies things. With just a bit more effort, you can use a little Sass interpolation to make a generic mixin that you can use to set any color attribute:

@mixin alpha-attribute($attribute, $color, $background) {
  $percent: alpha($color) * 100%;
  $opaque: opacify($color, 1);
  $solid-color: mix($opaque, $background, $percent);
  #{$attribute}: $solid-color;
  #{$attribute}: $color;
}

And finally, our updated code:

.button {
  @include alpha-attribute('background-color', rgba(black, 0.5), white);
}

Handy! To see this in action on a couple of my own buttons, check out this code pen.

November 18, 2013 ~ Intermediate, Guides and Tutorials, John W. Long