Basil Bourque
Basil Bourque

Reputation: 340230

Change to a relative color on hover in modern CSS

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.

Upvotes: 8

Views: 8287

Answers (5)

Penny Liu
Penny Liu

Reputation: 17498

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>

Upvotes: 3

the Hutt
the Hutt

Reputation: 18428

…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.

Upvotes: 1

Temani Afif
Temani Afif

Reputation: 274307

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>

Upvotes: 1

Akxe
Akxe

Reputation: 11595

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>

Upvotes: 0

nonopolarity
nonopolarity

Reputation: 151244

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>

Upvotes: 8

Related Questions