Build alternate element styles easily with currentColor

Last modified April 14, 2020
.* :☆゚

I was working on a new build today, and it’s a bit of a weird one because it uses a wacky colour scheme and many various colour ways containing interactive svg elements and alternate link button styles.

When you have many alternate styles of the same element, it can become challenging to manage consistency across the site when the text has to invert from light on dark, to dark on light on occasion.

currentColor Example

Managing consistency and the reliability of the CSS across the site is also made harder by the fact that the button links may need different :hover and :focus styles depending on the contrast and text its in.

On top of this, headers that are paired with SVG elements often have to change fill/stroke colours along with the text according to its focus state.

currentColor Example

I initially thought I could just encode the SVG elements as base64 and use them as background pseudo elements that contained manual overrides for each different hover/focus style. It quickly became apparent that the CSS would become unmaintainable and unwieldy. There had to be a better way.

I tried using currentColor at a point of desperation, because I was getting tired of maintaining the consistency of the SVGs and text colours across the site. Honestly, I’d heard of currentColor but never understood how it worked or why it existed. At this point there were so many exceptions on my build it was starting to get a little like this:

CSS lol

So you can imagine how mindblown I was when I realised currentColor was literally all I needed to maintain more understandable and concise CSS. It worked surprisingly well, so well in fact, that I wondered why I had never thought to use this in the first place for all the other websites I’ve done.

The magic and underrated value of currentColor

I know the currentColor keyword has existed for years now, but I’ve rarely used it apart from styling some CSS-based icons. Now that I think about it, it’s funny that I never thought to use it for SVGs as well, or just maintaining consistency in general. I’d rarely seen it used in other demos or boilerplates so it just never occurred to me just how useful it actually is.

currentColor is a weird part of CSS that flies under the radar, mainly because it’s not really it’s own specification and it feels out of place in CSS. It’s simply tacked on like an endnote on the color page on MDN, and it doesn’t feel like proper CSS to begin with because its naming convention is camel cased which is a weird thing to find in CSS world.

I think currentColor is absolute magic though, and now that I understand its power and potential, it has completely changed how I understand cascading styles and writing alternate colour ways for the same element.

The magic of currentColor lies in the fact that you can harness the power of the cascade so any children inherit the colour properties of its parent.

It is easier to see this in practice with an example:

See the Pen currentColor example by Jakki (@electrifried) on CodePen.

If you try changing the color value of the div, you can see the values of the border and SVG also change along with it. This is because the default colour is inherited from the specified color of itself or the nearest parent element, following the rules of the CSS cascade.

We can apply this same concept to writing alternate styles for elements such as button links.

For example, say I have a base .btn style for button links, like below:

a.btn {
  color: pink;
  padding: 10px 20px;
  border: 1px solid pink;
  margin: 20px auto;
  display: block;
}

I can declare alternate styles using currentColor like so:

a.btn {
  color: pink;
  padding: 10px 20px;
  border: 1px solid currentColor;
  margin: 20px auto;
  display: block;
  
  &.dark {
    color: navy
  }
}

With these styles in place, I now have two alternate button link styles I can use. It may seem simple enough, but .dark will automatically apply the border colour along with the text colour.

<a href="#" class="btn">Hello</a>
<a href="#" class="btn dark">Goodbye</a>

See it in action in a more fleshed out example below.

See the Pen currentColor example, with button links by Jakki (@electrifried) on CodePen.

There is a caveat with using currentColor particularly when inverting colours though, and that is, any color properties specified in children will override its parent. In the example below, I have to specify background-color manually in the hover styles otherwise color: #FFF; would override it.

a.btn {
  color: pink;
  padding: 8px 20px;
  border: 1px solid currentColor;
  margin: 20px auto;
  display: inline-block;
  text-decoration: none;
  &:hover {
    background-color: pink;
    color: #FFF;
  }
  &:focus {
    outline: 2px dotted currentColor;
  }

  &.dark {
    color: navy;
    &:hover {
      background-color: navy;
      color: #FFF;
    }
  }
}

In another example, say I have a bunch of themed sections on a page. I don’t even need to declare alternate .btn styles. I can simply set the default colour higher up in the cascade within the section and let currentColor do all the heavy lifting.

See the Pen currentColor example, with different colour ways by Jakki (@electrifried) on CodePen.

The above demo is quite a rudimentary and badly styled example to highlight the simplicity of the overall concept. If you try changing the color of each section, you’ll notice the input elements, inline svgs, and button links update automatically where currentColor is applied. The input elements even comes with a consistent hover style that spans across all sections, and this is made easier because we aren’t relying on exceptions or class-based rules.

MAGIC.

I am now using this concept in my own CSS and it’s revolutionised my code as well as cut down on all the overrides I would have otherwise needed.

If you want to see an exaple of this in action, you can visit this site I worked on.

In the meantime I hope this helped give you a better understanding of the power of currentColor, and how you can harness the cascade to write more understandable, robust, and concise CSS.