"currentColor", the first CSS variable
Tags: css, webdev
Published: 2019-04-29 13:57:37

---
title: "currentColor", the first CSS variable
published: true
description: "CSS got native variables not too long ago through Custom Properties (🎈🥳🎈), and they let us do some awesome stuff. But we shouldn't forget the grandfather of CSS variables, around long before Custom Properties came around: currentColor!"
tags: css, webdev
---

The recent addition to CSS of [Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*), a.k.a. CSS variables, was a very welcome addition to the language. It's opened the door for a lot of really cool techniques; there's a lot that you can only do when you can keep track of the state of your system and keep different bits in sync with each other, and variables give you a way to do that.

But here's something that developers newer to CSS may not know, and those who've been around often forget: we've actually had another variable in CSS since long before Custom Properties came on the scene. It's much simpler, and limited in scope, so it can't do everything Custom Properties can do, but it's *way* better supported, and with a bit of cleverness it can be used to accomplish some pretty cool stuff.

This variable is the special CSS keyword `currentColor`!

# What is it?

The [`currentColor` keyword](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentColor_keyword) is basically what it sounds like: it's a special keyword that holds the value of the `color` property at the location where it's used.

So for a very simple example, you can use it to make a pull quote box with a border that's the same color as the text in the box:

```css
blockquote {
  color: hotpink;
  border-color: currentColor;
}
```

{% codepen https://codepen.io/kenbellows/pen/ZZONYN default-tab=result %}

Snazzy, I think.

Interestingly though, in this particular case, the `border-color` rule is unnecessary. I always thought that the default `border-color` value was `black`, or else was set by the browser, but I recently discovered by accident that it actually defaults to `currentColor`! So if `border-color` just isn't specified, it will use `hotpink` by default!

Several properties actually default to `currentColor`:


* [border-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color)
* [caret-color](https://developer.mozilla.org/en-US/docs/Web/CSS/caret-color)
* [column-rule-color](https://developer.mozilla.org/en-US/docs/Web/CSS/column-rule-color)
* [text-decoration-color](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-color)
* [text-emphasis-color](https://developer.mozilla.org/en-US/docs/Web/CSS/text-emphasis-color)
* [outline-color](https://developer.mozilla.org/en-US/docs/Web/CSS/outline-color) (sometimes; read the link and read about the `invert` keyword, which is used if it's supported)

By the way, I didn't know about almost any of those rules before I looked up which rules default to `currentColor`! I need to read more about `text-emphasis`; it's really weird and interesting. Man, *every* time I dive into the docs to find something specific, I end up learning about something unexpected.


# Browser support

Of course, the first question you should ask whenever you learn about a cool feature of the web platform that you've never seen before is, "How good is its browser support? Can I actually use it?" Fortunately, the answers for `currentColor` are "super good" and "yes!"

Support actually goes back a really long time. Taking a look at [caniuse.com's overview of support](https://caniuse.com/#feat=currentColor), it's supported in every version of Edge, it's been in Chrome and Safari since version 4 (back then they used the same engine under the hood), and it's been in Firefox since version 2! Heck, it's even in Internet Explorer all the way back to IE 9! So don't worry about using it unless you're writing an intranet application for an organization that still hasn't upgraded past IE 8. (Tragically, I'm very aware that they still exist 😢)


# Demo: Badges

Okay, let's get practical.

I discovered `currentColor` while investigating the best way to implement a design for work. I needed to create a row of colored badges, each with a label on the badge and a numeric counter next to it. The background color of each badge matched the text color of its counter, and the label on each badge was colored to match the site background. For the sake of example, suppose the mockup was something like this:

![Three colored badges with white text in a horizontal row, each followed by a number whose text color matches the badge color: a red "Errors" badge followed by 123, a yellow "Warnings" badge followed by 45, and a green "Successes" badge followed by 12345](https://thepracticaldev.s3.amazonaws.com/i/0v3b8c0os92ymh08b5kw.png)

Each of those badges is identical, but for the color. Seems like a good use case for a reusable component! In a modern browser, you could use a CSS variable for the background of the badge and the foreground text color of its counter. But suppose you want/need to support IE 11, Edge 12-14, or another browser that doesn't support custom properties. Or maybe you already have some utility classes in your CSS to define text colors for various situations, like [Bootstrap's contextual color classes](https://getbootstrap.com/docs/3.4/css/#helper-classes-colors), e.g. `.text-danger` and `.text-warning`, so the idea of using the `color` property to set the badge color is super convenient. How might you go about it, armed with your new knowledge of `currentColor`?

First we'll need a root wrapper element for the component. This is where the color will be set, and it's where you'd add a class to override the color.

```html
<div class="badge">
</div>
```

```css
.badge {
  display: inline-block;
  color: cornflowerblue;
}
```

So what needs to be inside the badge component? Well, at first glance there are two regions: the bit with a colored background and white text, which I'll call the title block, and the digits off to the side that are colored to match the title block's background, which we've been calling the counter.

The title block definitely needs its own block in the DOM, since it has a background color, but the counter probably doesn't, since it's just sitting off to the side, which is what inline text does anyway. So lets try this markup:

```html
<div class="badge">
  <div class="title-block">
    Things
  </div>
  12345
</div>
```

Now the fun part! We want the background of the `.title-block` to match the `color` specified on the `.badge`, so we can use `background: currentColor`! We also want to set the `.title-block`'s text to white, according to our mockup, so let's add `color: white` as well. (If you've spotted the problem here, no spoilers!)

```css
.title-block {
  display: inline-block;
  padding: 0.5rem;
  background: currentColor;
  color: white;
}
```

Great! Let's see how it looks:

{% codepen https://codepen.io/kenbellows/pen/vMRLyP default-tab=result %}

Ah. Well. That's not what we wanted at all. The title block seems to be missing... or rather, it's completely white. Why is that?

Well, here's the thing: CSS is a declarative language, not an imperative one: it doesn't run top-to-bottom, keeping and updating state along the way. What this means is that when we write:

```css
.something {
  background: currentColor;
  color: white;
}
```

the browser doesn't figure out `currentColor`'s value, *then* set `color: white`. Instead, setting `color: white` changes the value of `currentColor` for the background to `white` as well! This is a limitation of `currentColor` that you need to keep in mind.

It's an easy enough fix, if a little annoying. We just need another layer of nesting to encapsulate the `color: white` rule. CSS rules often inherit downward to children, but never upward to parents, so this lets `.title-block` inherit its `currentColor` value from `.badge`, while being able to change the `color` within its child.


```html
<div class="badge">
  <div class="title-block">
    <span class="title-block-text">
      Things
    </span>
  </div>
  12345
</div>
```

```css
.title-block {
  display: inline-block;
  padding: 0.5rem;
  background: currentColor;
}
.title-block-text {
  color: white;
}
```

Now let's take another look:

{% codepen https://codepen.io/kenbellows/pen/rbdxpJ default-tab=result %}

Perfect!

Now that we've got our component, all we need to do is repeat it a few times and define a color-override class for each be instance.

```html
<div class="error badge">
  <div class="title-block">
    <span class="title-block-text">
      Errors
    </span>
  </div>
  123
</div>

<div class="warning badge">
  <div class="title-block">
    <span class="title-block-text">
      Warnings
    </span>
  </div>
  45
</div>

<div class="success badge">
  <div class="title-block">
    <span class="title-block-text">
      Successes
    </span>
  </div>
  12345
</div>
```

```css
.error {
  color: red;
}
.warning {
  color: goldenrod;
}
.success {
  color: green;
}
```

{% codepen https://codepen.io/kenbellows/pen/mgxPbV default-tab=result %}

Awesome! We met the requirement!

And this little badge component is pretty handy; there's still more to play with. We can try different colors, put emoji in the title area, add a background color to the counter area... Lots of possibilities!

{% codepen https://codepen.io/kenbellows/pen/ZZxEzz default-tab=result %}

What else can you come up with?



# Conclusion

To recap: there's a cool, undervalued keyword in CSS, `currentColor`, that can be used as a variable of sorts for certain use cases. It has much more broad support than CSS Custom Properties (a.k.a. CSS variables), and it is perhaps a bit more intuitive to use when developing a reusable component, since you only need to set the `color` property to populate it's value, which feels very nice.

However, it's clear that `currentColor` has limitations. The most glaring when comparing to Custom Properties is that it's only a color value, so it can't be used to store length values, image URLs, or fancy gradients. The other main point of caution is that you can't use an inherited `color` value in `currentColor`, say for the background or border color, while also setting your own `color` for text in the same block; setting `color` will update the value of `currentColor` everywhere within that block. You need to introduce a child element to keep your `color` value in a new scope.

So in short, it has limits and caveats, but I personally have found `currentColor` to be very useful, and it has let me write much cleaner code in a few tricky situations. My absolute favorite feature is just being able to set `color` on a root element of a component and see the whole thing update. Give it a try, see what you can do with it!