Dynamically theme-able websites using CSS currentColor
— 3rd of July 2016
First of all, what is currentColor?
CSS currentColor
is exactly what is sounds like.
It will take the elements' current computed color
value and allow other properties to use it.
Using currentColor to create themeable content
If you set the color on the html
or body
elements you can pick and choose different elements to use the currentColor
as one of their properties. If you then let people change that value, all of the elements using the html
's currentColor
will update too.
I'm not going to re-create the whole demo in this post, just some of the techniques used when creating it.
Change the color being inlined on the html
element below to see it in action.
1. Basic usage
I'm going to create a div nested inside another div, set the parent's color to blue, and then set the child elements' background to currentColor
. Just so we can see what happens.
<div class="div-1">
I'm blue
<div class="div-2">
da ba dee da ba die
</div>
</div>
.div-1 {
color: blue;
}
.div-2 {
background-color: currentColor;
}
Aaaaand the result:
Booyah.
Well, it's working, but it doesnt seem to be too useful. What's the point of setting the background color to the text color, you can't see anything...
If we set the color
of div-2
to white
, It'll have a blue background because of its parent, and the white text will make it legible again, right?
wrong.
Because the color of the element has changed, so has the currentColor
property.
The way I fix this is putting a span
inside whatever element I want to set the background of. That span
will ensure the text stays white without changing the currentColor
of the div with the blue background
<div class="div-1">
I'm blue
<div class="div-2">
<span class="white">
da ba dee da ba die
</span>
</div>
</div>
.div-1 {
color: blue;
}
.div-2 {
background-color: currentColor;
}
.white {
color: white;
}
Aaaaand the result:
Woooo! And if the text color of div-1 changes?
This is essentially all I've done for 90% of that demo.
Lightening and darkening the currentColor
This one would be a walk in the park in sass land with lighten()
and darken()
, but, we're not in sass land. No nesting, no loops, no mixins and no color functions. But what about the button in the demo? well...
background-image: linear-gradient
to the rescue!
because gradients are background images, and an element can have both background-color
and background-image
, and the background-image
always sits infront of the background-color
, if we set the background-image
to a linear-gradient
that uses two identical rgba()
values (so the gradient is a solid color) we can have a semi-transparent overlay above the color, effectively darkening it.
Instead of putting a span in my earlier example and making the text white, I'm going to darken the background with a translucent gradient.
<div class="div-1">
I'm not blue anymore
<div class="div-2">
and I'm somewhat legible again
</div>
</div>
.div-1 {
color: red;
background-color: #f2f2f2;
}
.div-2 {
background-color: currentColor;
background-image: linear-gradient(
-180deg,
rgba(0,0,0,0.50) 0%,
rgba(0,0,0,0.50) 100%
);
}
This is how I created the hover states, the artwork under the hero, and the lightened and darkened sections.
Instead of using 20% black, try using 80% white, or other colours and blend modes for different effects.
Bonus artwork demo:
four semi-transparent divs sitting in a div with a currentColor
background giving the illusion of the color darkening
.artwork {
display: flex;
width: 100%;
height: 3em;
background: currentcolor
}
.artwork > * {
width: 25%;
height: 100%
}
.one { background: rgba(0,0,0,0.1) }
.two { background: rgba(0,0,0,0.3) }
.three { background: rgba(0,0,0,0.5) }
.four { background: rgba(0,0,0,0.7) }
Go forth and theme-ify
You can use currentColor
to fill an SVG, set backgrounds, borders and whatever else you might want to do with it. It's exactly the same as using a color.
Fill SVG's
svg {
fill: currentColor;
}
Blend currentColor with an image
.blend {
background: currentColor url('image.jpg');
background-size: cover;
background-blend-mode: multiply;
}
Set the border of an active menu item link?
li.active {
border-bottom: 3px solid currentColor
}