The Power of the rgba() Color Function in CSS

Avatar of Ahmad Shadeed
Ahmad Shadeed on

One of the things that I’m really interested in about CSS is the new color-mod function. It will give us the ability to do color manipulations right in the browser. For example, when hovering over a button, you can change the color by using something like color: color(black darkness(50%));, without the use of any CSS preprocessor like Sass.

But as the support of these CSS color functions is zero nowadays, we can temporarily use PostCSS and compile them as regular colors. Or we can experiment and discover the power of CSS rgba() color functions to change colors on the fly! Let’s see how we can use it.

How it works

basic idea

In a design app, when we place a black and white boxes over a bigger box with a blue background color (As in the example), the result will be a lighter and darker blue, respectively.

That’s because when decreasing the opacity, the colors will blend together based on if it’s white or black. Can you expect what will happen if we changed the blue background to green? You guessed it!

Basic Idea Green

As you see, by changing the background color to green, the small boxes looks different now! We have light and dark green. We also can change the opacity value to pick a darker or lighter color. Let’s work off this basic premise to dive into some real-world examples.

Applying the concept

To keep the above example concise, we played with the opacity. In our actual design, we will need to use rgba() alpha value.

.header {
  background: rgba(0, 0, 0, 0.5); /* Black color with 50% alpha/opacity */
}

We’ll use the background instead of opacity here because if we used the opacity value, all of the child elements will be affected, which is not what we want to achieve. If we use the alpha channel of the background property, we’re ensured that we’ll only update the element that we’d like to change.

Note: in the demos we will use Sass rgba() function to make things faster. For example:

.elem {
  background: rgba(white, 0.5);
}

will be translated to:

.elem {
  background: rgba(255, 255, 255, 0.5);
}

Theming a website header

The first use case for rgba() is to theme a web app header. In Trello they are using a background color with rgba() for the header child elements (logo, search input, buttons):

.search {
  background: rgba(255, 255, 255, 0.5); /* White with 50% alpha */
}
Trello with Devtools

With that in place, we will get the ability to theme the header by only changing its background, and then the child elements will change as well.

In our example, we will make something similar of Trello header and play with the background from dev tools.

Trello Header

Notice how the child elements background color is different in the 2 headers. If we want to inspect element and change the parent background, we can theme our header very easily.

Theming Header

See the Pen Header by Ahmad Shadeed (@shadeed) on CodePen.

Article header

Article Header

In this example, using rgba() will be beneficial for:

  • Borders at the top and bottom edges.
  • Background color for the centered wrapper.
  • Background color for the category link.
Article Header Annotated
.parent {
  background: #5aaf4c; /* parent background */
  box-shadow: 
    inset 0 8px 0 0 rgba(255, 255, 255, 0.5), 
    inset 0 -8px 0 0 rgba(255, 255, 255, 0.5); /* top and bottom borders */
}

.contain {
  background: rgba(0, 0, 0, 0.1);
}

.category {
  background: rgba(255, 255, 255, 0.5);
}

See the Pen Article Header by Ahmad Shadeed (@shadeed) on CodePen.

Buttons

When theming buttons, we can use rgba() to make the hover and focus effects for things like borders, shadows.

.button {
  background: #026aa7;
  box-shadow: inset 0 -4px 0 0 rgba(0, 0, 0, 0.2);
}

.button:hover {
  box-shadow: inset 0 -4px 0 0 rgba(0, 0, 0, 0.6), 0 0 8px 0 rgba(0, 0, 0, 0.5);
}

.button:focus {
  box-shadow: inset 0 3px 5px 0 rgba(0, 0, 0, 0.2);
}

See the Pen Buttons by Ahmad Shadeed (@shadeed) on CodePen.

Gradients

Another useful use case is to add the background as a solid color and then use a pseudo element with a rgba() colors for the gradient color stops.

Gradients
.elem {
  background: green;
}

.elem:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(to right, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.7));
}

This will also give us the ability to animate the gradients by only changing the background color.

.elem {
  /* other styles */
  animation: bg 2s ease-out alternate infinite;
}

@keyframes bg 
  to {
    background: green;
  }
}

See the Pen Gradients by Ahmad Shadeed (@shadeed) on CodePen.

Sub Element

If we have a navigation list inside a header element, we can add a background color with rgba() to the navigation. This will make the background a bit transparent and so it will blend with the parent background.

See the Pen Sub Element by Ahmad Shadeed (@shadeed) on CodePen.

And the same could be used for making dynamic hover effects:

See the Pen Hover Effect by Ahmad Shadeed (@shadeed) on CodePen.

Dark/Light Variations of a color palette

We can use this concept to generate different shades of a specific color palette by positioning a pseudo element on each color box with a specific rgba() value.

See the Pen Color Palette by Ahmad Shadeed (@shadeed) on CodePen.

Image Effects

If we want to make an image darker or lighter, we can use a pseudo element with rgba() background.

By using a colored background, we can create a color tint effect. Other than that, we can use mix-blend-mode property to blend the background with the image so we can different results.

It’s important to check support tables before using mix-blend-mode:

.elem:before {
  background: rgba(0, 0, 0, 1);
  mix-blend-mode: color;
}

If mix-blend-mode is not supported, the image will be black and the user won’t get it. It’s better to work on such effects as an enhancement, but don’t depend on it. To do so, you can use @support or Modernizr.

@supports (mix-blend-mode: color) {
  /* your enhanced styles go there */
}

See the Pen Images by Ahmad Shadeed (@shadeed) on CodePen.

Theming with CSS Variables

By using CSS Variables (custom properties) for the parent elements, when the variable is changed then all child elements will be affected. For example:

:root {
  --brand-color: #026aa7;
}

/* Checking for the support of CSS Variables */
@supports (--color: red) {
  .elem {
    background: var(--brand-color);
  }
}
var colors = ["#026aa7", "#5aaf4c", "#00bcd4", "#af4c4c"];
var colorOptions = document.querySelectorAll(".option");
var colorLabels = document.querySelectorAll(".option + label");

for (var i = 0; i < colorOptions.length; i++) {

  /* Add an event listener to each radio button */
  colorOptions[i].addEventListener('click', changeColor);

  /* Add a value to each radio button based on colors[] array */
  colorOptions[i].value = colors[i];

  colorLabels[i].style.background = colors[i];
}

function changeColor(e) {
  /* calling the root element and set the value of a specific property. In our case: --brand-color */
  document.documentElement.style.setProperty('--brand-color', e.target.value);
}

By combining CSS Variables and rgba(), we can make our layouts and colors a bit more dynamic without re-defining a new color for each element.

See the Pen Header – CSS Variables by Ahmad Shadeed (@shadeed) on CodePen.

Things to take in consideration

Fallback Color

Although the global support for CSS colors is 97.39%, it’s important to provide a fallback for non-supporting browsers.

.elem {
  background: #fff; 
  background: rgba(255, 255, 255, 0.5); /* non supporting browsers will ignore this declaration */
}

Color Contrast Check

We should ensure that the contrast between elements meets the accessibility guidelines. Sometimes, using rgba() might result in a poor color that is very hard to read. You can use tools like Lea Verou’s Contrast Check to help determine if colors meet accessibility standards.