Change to a relative color on hover in modern CSS
Asked Answered
G

5

8

I want react to hovering on a link:

/* mouse over link */
a:hover {
    text-decoration: none ;
    border-bottom: 1px dotted ;
}

…to alter slightly the background color around the text. Rather than specify a certain color, I want to just lighten or darken whatever the inherited color as currently set. For hover and active on a link, I want the background color to change, to give something of the effect of a button being pressed.

I want to be able to alter the background color of the text or page without having to alter the specific color in the a:hover rule too.

Goliard answered 6/1, 2020 at 1:48 Comment(5)
SCSS can do the lighten or darken of colours so you can say "lighten($color, .2)" to lighten a colour by 20%.You could set the background colour as a different lighten, or darken, percentage of the original colour to keep the ratio consistent between the hover and the background. More on SCSS here: sass-lang.com. Or you can use CSS variables:Dysteleology
@NathanielFlick Thanks for the tip. I am hoping to do this in straight CSS if possible.Goliard
CSS doesn't have colour functions, but it does have colour variables. SASS compiles to CSS so basically the same thing. :)Dysteleology
You may want to see filter: brightness(), though this alters the color of the text rather than the background color.Presumptuous
@Presumptuous For hover and active on a link, I want the background color to change, to give something of the effect of a button being pressed.Goliard
J
8

You can use filter: brightness(), although you also have to specify a particular color on the body background and background of a to be inherit. The default value of background-color is transparent and cannot be darkened. It needs to be changed to inherit to get a particular color so that darkening can work. If it is transparent, the alpha is 0 and is not subject to darkening or brightening.

However, if the link is inside a div and the div doesn't have a specific background color, then it'd be transparent, and the link would inherit that background color. So the link needs to have a particular background color to be darkened.

I did a window.getComputedStyle($0)["background-color"] where the $0 was the div selected in the developer's console, and the result was "rgba(0, 0, 0, 0)", meaning transparent.

body { background: white }

a { background: inherit; border-radius: 2px }

a:hover {
    text-decoration: none;
    border-bottom: 1px dotted #ccc;
    filter: brightness(.8);
}
<a href="http://www.google.com">Google</a>
Jennyjeno answered 6/1, 2020 at 2:25 Comment(0)
I
3

For such scenarios, I typically utilize HSL color values. This eliminates the need to manually copy colors across multiple elements, as you can easily adjust the lightness component of the color. HSL color model is more human-readable than Hex code (#F37022).

HSL color values are specified with: hsl(hue, saturation, lightness).

a {
  width: auto;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  margin: 0.5rem 0;
  padding: 1rem 2rem;
  color: white;
}

.color {
  --hue: 22;
  --saturation: 90%;
  --lightness: 54%;
  background-color: hsl(var(--hue), var(--saturation), var(--lightness));
}

.color.light:hover {
  --lightness: 80%;
  /* 20% light */
}

.color.dark:hover {
  --lightness: 40%;
  /* 20% dark */
}
<a class='color light'>Hermès</a>
<a class='color dark'>Hermès</a>
Isomagnetic answered 14/8, 2021 at 15:11 Comment(0)
N
1

You can consider an extra layer above the background where you apply white or black coloration to make the background lighter or darker:

a {
  display:inline-block;
  padding:10px;
  color:#fff;
  position:relative;
  z-index:0;
}
.red {
  background:red;
}
.blue {
  background:blue;
}
.green {
  background:green;
}
.light:before,
.dark:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background:rgba(255,255,255,0.3);
  opacity:0;
}
.dark:before {
  background:rgba(0,0,0,0.3);
}

a:hover::before {
  opacity:1;
}
<a class="red light" href="">some text here</a>
<a class="red dark" href="">some text here</a>
<a class="blue light" href="">some text here</a>
<a class="blue dark" href="">some text here</a>
<a class="green light" href="">some text here</a>
<a class="green dark" href="">some text here</a>

A similar idea without pseudo element

a {
  display:inline-block;
  padding:10px;
  color:#fff;
}
.red {
  background:red;
}
.blue {
  background-color:blue;
}
.green {
  background:green;
}

.light {
  background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3));
}
.dark {
  background-image:linear-gradient(rgba(0,0,0,0.3),rgba(0,0,0,0.3));
}

.light,
.dark {
  background-size:0 0;
}

a:hover {
  background-size:100% 100%;
}
<a class="red light" href="">some text here</a>
<a class="red dark" href="">some text here</a>
<a class="blue light" href="">some text here</a>
<a class="blue dark" href="">some text here</a>
<a class="green light" href="">some text here</a>
<a class="green dark" href="">some text here</a>
Neoimpressionism answered 6/1, 2020 at 10:10 Comment(0)
U
1

…to alter slightly the background color around the text.

If you want the color exactly around text then text-shadow can be used:

a {
  font: bold 2em serif;
  text-decoration: none;
  margin-right: 5px;
  color: inherit;
}

a:hover {
  text-shadow: 1px 0px 2px #000, 1px 0 9px #000;
  /* text-shadow: 1px 0px 2px #000, -1px 0 2px #000; */
}

a:active {
  text-shadow: 0px 0px 6px #000, 1px 1px 2px #000;
  color: #fff8;
  filter: contrast(20) opacity(0.5);
}
<div style="background-color: white; color:blue ">
  <a href="#">One</a>
  <a href="#">Two</a>
  <a href="#">Three</a>
</div>
<div style="background-color: wheat; color:#D06224 ">
  <a href="#">One</a>
  <a href="#">Two</a>
  <a href="#">Three</a>
</div>
<div style="background-color: lightgreen; color:#172774">
  <a href="#">One</a>
  <a href="#">Two</a>
  <a href="#">Three</a>
</div>
<div style="background-color: lightseagreen; color: lightsalmon">
  <a href="#">One</a>
  <a href="#">Two</a>
  <a href="#">Three</a>
</div>

The shadow automatically gets blurred depending on the blur-radius and blends with the background. You don't have to provide extra opacity.
On hover I am darkening the area around the text and on click(active), I am making text transparent so that it takes background color.
Untrimmed answered 5/12, 2021 at 16:36 Comment(0)
E
0

As of now, this is not possible with css alone. You could use preprocessing like SASS.

Then you could shift hue using filter rule.

Lastly, probably what you wanted, there is color-mod() rule in works, but I haven’t heard of it lately.

Reference: https://www.w3.org/TR/css-color-4/


PS: I did remember to sometimes use:

a {
  background: rgba(255, 0, 0, 1);
}

a:hover {
  background: rgba(255, 0, 0, .8);
}

div {
  display: inline-block;
  background: black;
}

div + div {
  background: white;
}
<div><a>Hover me, darken</a></div>
<div><a>Hover me, lighten</a></div>
Estellestella answered 6/1, 2020 at 2:34 Comment(2)
Pre-processing with SASS only outputs CSS so it is entirely possible with CSS alone.Towroy
@Rob, having JS in page will also end up with CSS there... the point is you will have to do some additional overhead to have this working, unlike the color-mod() function that would run out of the box.Estellestella

© 2022 - 2024 — McMap. All rights reserved.