Adobe Creative Cloud

February 24, 2015 /Code /

Extending the Color Cascade with the CSS currentColor Variable

If you use Sass or LESS, then you probably already use variables in your style sheets and know how useful they are. If you don’t use a preprocessor, then you might be curious what the fuss is all about and why variables are so popular and how they can be useful. In this article, we’re going to get an overview of why variables are useful, and get acquainted with one particular variable: currentColor.

What are variables good for?

Variables in CSS are useful because they allow us to write more DRY (Don’t Repeat Yourself) code. They are also particularly useful for managing and maintaining large-scale projects that contain a lot of repeated values.

One of the most common use cases for variables are color themes/schemes throughout a website or application. With variables, creating and managing color schemes across a CSS document becomes a lot easier. For example, color schemes usually require you to reuse a few color values for different properties in the CSS file. If you want to change the primary color of a scheme, you would normally have to change all occurrences of that color in the style sheet. Using CSS variables, you can define a variable in one place (for example a variable named “primary-color”), assign a color value to it, and then use the variable as a value anywhere you want in the style sheet. Then, when the time comes to change this color, all you would have to do is assign it a different color value, and all occurrences of that variable in the style sheet will be automatically updated.

CSS 2.1 did not introduce variables. (Although, that’s not entirely true, as you will see in this article.) In 2014, native CSS variables that are similar to preprocessor variables were introduced; these variables are arguably even more capable than preprocessor variables. A CSS variable is accepted as a value by all CSS properties.

In addition to the new variables, CSS already comes with a keyword value that is practically also a variable: the currentColor keyword.

The currentColor keyword

The currentColor keyword is like a CSS variable, except that it has one main restriction: you can only use it where a <color> value is expected; if a property does not accept a <color> value, it will not accept currentColor as a value.

The following are all examples of using currentColor in properties that accept it as a value.

box-shadow: inset 2px 2px 3px currentColor;
background-color: currentColor; /* not a good idea! */
background-image: linear-gradient(currentColor, transparent);

Another difference between currentColor and other variables is that you don’t get to assign a value to it the same way you would assign other variables values. The value of currentColor is determined by the computed value of the color property that is currently being used on the element. That is, the value of currentColor is equal to the current color property value. And this is where the currentColor name comes from.

So, if we were to go back to our previous example, the currentColor keyword sets the box shadow color to whatever color value you have set on the div. If you haven’t set any color, it will use the inherited color from any of the div’s ancestors. If no ancestor has a color, most browsers will just default to black.

Put another way: the currentColor keyword is used to make properties of an element, or child elements of an element, inherit the color set by the element’s color property. It therefore acts as the inherit value to allow inheritance of a color that would otherwise not be inherited by a property or child element.

This also means that, for properties that already inherit the color value, currentColor will not be of much use.

Properties and elements that inherit the color value by default

When an element has a color value, whether it is explicitly set or inherited, some of the foreground elements of that element that accept a <color> value will inherit that color value by default.

For example, an element’s borders are part of the element’s foreground; thus, even if you don’t specify a border color, the border will get the same color as the color property value. If the element does not have one, most browsers usually default to black.

The border color in this example will be purple:

.parent {
    color: purple;
}

.child {
    border: 5px solid; /* we didn’t specify the border color here */
}

The elements that will get/inherit the element’s color value include:

  • The element’s text—it is what the color property is used for.
  • The text’s outline.
  • The element’s border.
  • The element’s box shadow.
  • An img’s alt text. That is, when the image cannot be displayed, the text that appears in its stead will have that color value.
  • A list item’s bullet(s) and border.
  • In some browsers (e.g Chrome) the horizontal rule’s (<hr>) border color. (Without a border, the color will not be affected.)

When you set these element’s properties on an element without explicitly assigning them a color, they will inherit the computed color value of the element by default.

The following demo shows the above elements in action as they inherit the color set on the page’s body. Change the color property value on the body to see these elements’ colors also change.

See the Pen currentColor — Adobe DW Blog by Sara Soueidan (@SaraSoueidan) on CodePen.

At this point, you might be wondering: if so many properties/elements already inherit the color value, how or where can currentColor be useful?  

Extending color inheritance with currentColor

There are some places where retrieving the color value and using it could come in handy. One example where currentColor can be used that would not otherwise inherit the color value is gradients. CSS gradient images, be that linear or radial gradients, do not inherit colors. By using currentColor, you can make a linear gradient used as a background image, for example, adjust to match any color you specify somewhere else as the “primary color” of a theme.

background-image: linear-gradient(to bottom, currentColor, #fff);

Such an example was created by Scott Kellum who took this concept a little further and added an animation to the color property. As the color property animates, all the elements affected by that color will also animate their colors.   See the Pen currentColor by Scott Kellum (@scottkellum) on CodePen.

This is a great example of using currentColor, particularly the animation part.

However, more practical examples for currentColor exist. Let’s take a look at some of them.

currentColor Use Cases

The idea behind currentColor is to extend the color cascade. This comes in handy in a lot scenarios.

currentColor for theming UI components

From the previous demo, we can move to a more practical (and brilliant, I must say) use case for currentColor demonstrated by Simon “Simurai” in a talk he gave at CSSConfau last year. The talk was about how we can use Flexbox, currentColor and em units inside UI components to quickly style entire Web Apps straight in the browser.

To demonstrate the usefulness of currentColor, Simon created a set of UI elements, including some sliders. These elements have the same color scheme applied. For coloring the sliders and input types, he used the currentColor variable to force the color inheritance in the background color of the slider’s thumb and checkboxes that would otherwise not inherit that color.

currentColor-slider

An example using currentColor to apply the color property’s value to the slider’s thumb. (Source)

Similarly, more UI components can be created that inherit a color value that you would specify somewhere up in the cascade. With this, a UI theme is established on these components. Then, leveraging the cascade and currentColor, you can change the main color value and get a new set of colored components every time you do, thus practically automating the process.

The following GIF image shows that in action. Simon is using the browser devtools and the color picker in the browser to change the value of the color property, and get a live preview of these changes on the components.

Changing the value of the color property will update the colors of all UI components that are inheriting this color, with the help of the currentColor variable. (Source)

 

Using the browser’s devtools capabilities, you would be able to change the theme to your liking and then save the changes to your working files right from the browser. To learn all about it, refer to Simon’s talk and blog post.

currentColor for theming and styling SVG

SVGs are great, but they come with a few styling quirks and limitations depending on how you use them. One such case is reusing parts of an SVG using the SVG <use> element.

If you’re not familiar with the <use> element, you can read all about it here. The idea behind <use> is to reuse parts of an SVG anywhere we want these parts to appear on the page. By useing an SVG element, we’re practically creating a live copy of that element. This is similar to copy-pasting the element in a graphics editor, except that the copy is live—meaning that its characteristics can change as the original copy changes.

The <use> element is used a lot when creating SVG sprites. An SVG containing all of the icons would be used as the sprite, and then we can insert individual icons from that sprite anywhere on the page, using <use>. You can read all about SVG creating sprites in this article.

When an element is used, however, the copy of its contents is cloned into a shadow DOM. This means that these contents cannot be selected and styled with CSS the way we would select and style SVG elements or even HTML elements present in the regular DOM. This is one reason why styling SVG icons created like that is limited.

Using currentColor, we can work around this limitation but allowing a color we specify in CSS “leak” into the contents of the used SVG, by setting currentColor as a value for the properties we want the color value to leak into.

So with an SVG icon used like so:

<svg class="home-icon">
    <use xlink:href="#home"></use>
</svg>

And assuming the #home icon defined in the sprite sheet contains something like:

<symbol id="home">
    <rect id="bottom" fill="currentColor" ... />
    <polygon id="roof" ... />
</symbol>

We can then apply styles to the icon and have the fill color cascade down to the #roof (which does not have a fill attribute above) and the color value be inherited by the #bottom rectangle’s fill attribute:

.home-icon {
    fill: red;
    color: white;
}

The fill color will cascade down from the svg to use and then to #roof. The color value will be used as a value for the #bottom fill color because of currentColor.

Fabrice Weinberg wrote an article about this technique a while back on his Codepen blog.

This technique comes in handy when you want to create multiple icons each having different colors; all you would have to do in that case is change the color and fill values in the CSS. An example of this usage is the following demo Fabrice shows in his post:

See the Pen Sass SVG Icons 1.1KB by Fabrice Weinberg (@FWeinb) on CodePen.

Of course, you can use currentColor on multiple elements inside the SVG. However, as you probably have noticed, this only allows you to change two colors inside the SVG.

If you want to have more control over colors and specify more color values that you could leak into the SVG, you would need more variables; this is where the new CSS Variables specification will come in handy. You can read more about this here.

Final Words

In the previous examples, we saw how we can use currentColor in multiple places, and then change the colors we want in one place and have that color be applied to those multiple places, instead of having created multiple occurances of the same color and then changed all of them. This helps us write shorter CSS, and provides us with some sort of automation, especially in situations like the UI components we saw in Simon’s talk.

With CSS Variables, you will be able to define your own set of variables and use them in similar and much, much more use cases, as the new variables will be valid values for any CSS property, not only those that accept <color> values. Dealing with SVG icons will certainly become easier, as will maintaining large-scale projects. Again, if you use a preprocessor, then you already know how useful variables are.

Can you think of more use cases for currentColor? If so, make sure you share them in the comments below!

Code

Join the discussion

  • By Globview - 9:10 PM on February 26, 2015  

    This is a great with, sprites, and Mixins. I love it.

  • By Nick - 7:34 AM on February 28, 2015  

    Which browsers support the currentColor keyword?

  • By James Jardine - 4:10 PM on March 2, 2015  

    Good read and something real useful in UI app design, but in your first example, you say that applying currentColor to a background property is not a good idea, but you reference Simon as an example in one of your use cases. In his example, one of the UI elements is doing so. Can you elaborate on why this is not a good idea?

    • By Sara Soueidan - 8:00 PM on March 3, 2015  

      Hi James

      Indeed the example says it’s not a good idea because the color in that example will be the same as the text color. We have `color` for the text, and then setting background-color to `currentColor` will inherit the text color and use it as a background color, making the content completely unreadable.

      Simon’s example does not have any text on background, which is why it is okay.

      I hope that helps and thank you for your question!

      –Sara

  • By Paolo - 2:11 PM on March 3, 2015  

    Good article, thanks for the inspiration.

  • By matt - 6:11 PM on March 3, 2015  

    My worry using this would be losing track of what the currentColor is in large stylesheets. Any tips for dealing with that?

    • By Sara Soueidan - 8:01 PM on March 3, 2015  

      I’m afraid that would require some planning ahead—which is never a bad idea and always something we should do, right?

      If you know your components and how they are structured and themed, my guess is this will come naturally.

      For anything more complicated, a custom CSS variable might be the better option.

      Cheers!

      –Sara