The best way to write alternate element styles, using currentColor

Published November 1, 2019
.* :☆゚

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 have to maintain the same colour text and border colour when they are hovered or focused in differently themed sections.

On top of this, I have headers that are paired with SVG elements, and these have to change stroke colour along with the text depending on what section it is in.

currentColor Example

My initial thought was to encode the SVG elements as base64 and use them as background pseudo elements. I would then use each theme’s section class to style CSS overrides on the different elements inside it such as button links. 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. There were so many exceptions 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’ve 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 to direct the default colour on to other styles such as borders or background colours.

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 automatically 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 though that you may have noticed, and that is you cannot specify a different colour to use alongside it. This means that you will still have to specify the hover styles individually if you want to invert colours.

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 my case where I have themed sections, 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.

I’ll update this post when the full site I’m working on at the moment is built and live so you can see the concept in action.

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.