Is there a keyword like currentcolor
which allows us to get the color of a class in its default state?
For example, I'm trying to create a re-useable button style, and currentcolor
keyword helps a lot until I try to create the :hovered
state.
.outline-btn {
background-color: transparent;
border: 1px solid currentColor;
padding: 0.5em 1.5em;
}
.rounded-btn {
border-radius: 50px;
}
The default state looks the way we want and changing the color
or the font-size
would also adjust the rest of the properties.
But we want the :hovered
state to invert the colors (white text and orange background in this case)
.outline-btn:hover, .outline-btn:active, .outline-btn:focus {
background-color: currentcolor;
color: white;
}
But since in this state the color
becomes white, everything else also turns white.
Is there a way that we can achieve the behavior that we want without having to create multiple classes for the different button styles that we want?
Desired effect on hover:
Also I forgot to mention that I am using SCSS
if that helps.
Thanks for your time :)
This can be done with CSS only. Works for any two colours, provided that one is set on background-color
and one is set on color
.
.button--orange {
background-color: white;
color: orange;
}
/* CSS beyond this point is colour-agnostic - no mention of either white or orange */
.button {
border: 0.125rem solid currentColor;
padding: 0.5rem 1rem;
font-size: 1rem;
position: relative;
}
.button, .button::before {
border-radius: 5rem;
}
.button:hover::before {
content: "";
position: absolute;
z-index: 1;
inset: 0;
background-color: currentColor;
}
.button:hover span {
position: relative;
z-index: 2;
background-color: inherit;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
<button class="button button--orange">
<span>Button</span>
</button>
This works by establishing 3 layers.
The first, .button
, is the button itself with the default background colour and text colour that appear when not hovered.
The second, .button::before
, is a layer that appears when hovered to invert the background colour. It uses the text colour of the button by having its background colour set to currentColor. The reason we need this layer instead of simply setting background-color: currentColor
on .button
is because we need to keep the background colour intact for the third layer.
The third layer, .button span
, contains the text of the button. The goal is to set its colour to the background colour of the original button on hover.
We can't simply set the color
property because in theory we don't know what to set it to. We need to copy the parent element's background colour, but it could be anything. If there were a currentColor
that contained the value of the parent's background colour, this would be trivial.
Instead we can use -webkit-background-clip
, a feature which has been around for ages and is commonly used to create gradients in text, but we can use it for regular colours too. We can copy the background from the parent with inherit
and clip it to the text, which results in the visual appearance of text that is the same colour as the parent's background.
The second layer provides enough contrast to make the text visible, and the colour swap is complete.
An alternative, and perhaps better, approach would be to save the text colour and background colour into CSS variables (or SCSS variables as @alexbea suggests) and then reference those in the hover states of the button. But I just wanted to prove that this question can indeed be answered as originally asked.