67

Assuming an element is at 100% saturation, opacity, etc... how can I have its background become slightly lighter when it is hovered?

The use case is that I'm allowing a user to hover over any element on a page. I don't want to go around determining each colors equivalent at 80% opacity.

One method is to change the opacity: 0.4 but I only want the background to change.

Don P
  • 60,113
  • 114
  • 300
  • 432
  • dim everything else, since the element's already as bright as it could get. – Marc B Apr 23 '13 at 20:18
  • Use RGBA instead of opacity unless you are using an image of some sort. – Michael Apr 23 '13 at 20:19
  • is it a colour you want to change or an background image? If the colour you can use a HSL() value and increase the lightness value (the last one). – David Storey Apr 23 '13 at 20:19
  • @Marc No thanks, that would look pretty terrible given this situation :) – Don P Apr 23 '13 at 20:19
  • @Michael, thanks but these are already set with their "a" = 1. So doesn't really help me here. – Don P Apr 23 '13 at 20:20
  • @dstorey - I only want to change the background color – Don P Apr 23 '13 at 20:21
  • if say the background colour is set using background-color: hsl(0,0%,0%); you can set on hover to be something like background-color: hsl(0,0%,50%); – David Storey Apr 23 '13 at 20:24
  • I'm afraid this isn't possible with CSS alone. Please see my answer and this related question: http://stackoverflow.com/questions/1625681/dynamically-change-color-to-lighter-or-darker-by-percentage-css-javascript – Chris Bier Apr 23 '13 at 20:38
  • @DonP you should mark del4y's answer as the accepted answer. Seems to do exactly what we want. – LaVache Aug 30 '17 at 01:20

7 Answers7

98

It's a long time ago but you can do something like this:

.element {
    background-color: red;
}
.element:hover {
    box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);
}

You can change the 100px into a number you want. I took a large one to cover the whole element.

It isn't a very beautiful solution but it works!

Here an example: http://jsfiddle.net/6nkh3u7k/5/

del4y
  • 1,162
  • 8
  • 10
  • 10
    This is absolutely sweet! the best thing is it works on elements with any kind of background or gradient etc. This should be the accepted answer IMO. Note that the `inset` value should be last not first though. – beercohol Jun 23 '15 at 16:24
  • 1
    This also works to darken an element if you change the three `255` to `0` which will change white to black. – styfle Apr 24 '18 at 23:59
  • 1
    I like this. It's better than `filter: brightness` because it doesn't cause the text to blur – Nodeocrat Sep 17 '20 at 18:07
95

Here's an easy way to do it:

.myElement:hover {
  filter: brightness(150%);
}
satnam
  • 10,719
  • 5
  • 32
  • 42
  • 1
    This actually is a good quick and easy solution if you don't need to support IE11. Filter's are the future for sure though, rather than having to use a pseudo element hack. However answer should be edited to remove the -webkit prefix. – Trevor May 11 '17 at 00:04
  • 4
    Problem with filters is, it makes text blurry – Nodeocrat Sep 17 '20 at 17:50
  • This helped me with a transparent PNG vuetify.js v-img, as the box-shadow solution was brightening the whole squared image as opposed as just the image, maybe I wasn't targetting `.v-image__image` correctly or whatever, but why bother with that if this just worked, thanks! – ajax333221 Aug 07 '21 at 19:50
23

I'm using box-shadow property to control the brightness of the background color, by placing a translucent overlay

Example:

.btn {

  background-color: #0077dd;
  
  display: inline-flex;
  align-content: center;
  padding: 1em 2em;
  border-radius: 5px;
  color: white;
  font-size: 18px;
  margin: 0.5em;
  cursor: pointer;
}

.btn.brighten:hover {
  box-shadow: inset 0 0 0 10em rgba(255, 255, 255, 0.3);
}

.btn.darken:hover {
  box-shadow: inset 0em 0em 0em 10em rgba(0, 0, 0, 0.3);
}
<span class="btn brighten">Brighten on Hover</span>
<span class="btn darken">Darken on Hover</span>
Arik
  • 5,266
  • 1
  • 27
  • 26
11

you should use the RGBa method (background-color:rgba(R,G,B,alpha);) to do this:

.element{
    background-color:rgba(0,0,0,1); /*where 1 stands for 100% opacity*/
} 
.element:hover{
    background-color:rgba(0,0,0,0.5); /*where 0.5 stands for 50% opacity*/
}

FIDDLE

AND if you strongly need to make it work in IE8 or lower too here is how it comes:

.element:hover{
background: transparent;
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#7F000000,endColorstr=#7F000000)"; /* IE8 */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7F000000,endColorstr=#7F000000);   /* IE6 & 7 */
      zoom: 1;
}

note that the startColorstr and endColorstr values are built like this #AARRGGBB (where AA is the Alpha channel) and must be the same if you don't want a gradient effect from a color to another.

Yenn
  • 919
  • 6
  • 20
  • This is a better solution than mine, but `rgba()` isn't supported in IE8: http://caniuse.com/#search=rgba –  Apr 23 '13 at 20:29
  • @Ghodmode This question is tagged `CSS3` – Roko C. Buljan Apr 23 '13 at 20:31
  • @roXon both pseudo-elements and `rgba()` are included in the CSS3 specification. Using CSS3 doesn't necessarily preclude support for IE8. I was just pointing out a possible drawback of using `rgba()`. –  Apr 23 '13 at 20:44
  • i just think that we are now on v10 of IE, an (awful) browser that automatically updates itself together with the OS. people who use v8 or lower just dont know how to use a computer. Anyway i'm updating my answer with the IE8(and lower) solution. – Yenn Apr 23 '13 at 21:22
5

I would use a :after pseudo-element instead of a conventional background. It's supported in IE8, where rgba() isn't.

HTML:

<div class="hoverme">
    <p>Lorem ipsem gimme a dollar!</p>
</div>

CSS:

.hoverme {
    position: relative;
}
.hoverme:after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    background-color: #fff;
    z-index: -1;
}

.hoverme:hover:after {
    background-color: #ddd;
}

or something like that.

http://caniuse.com/#search=%3Aafter

For a smoother result, add a CSS3 transition:

.hoverme:after {
  -webkit-transition: all 0.3s ease-out;  /* Chrome 1-25, Safari 3.2+ */
     -moz-transition: all 0.3s ease-out;  /* Firefox 4-15 */
       -o-transition: all 0.3s ease-out;  /* Opera 10.50–12.00 */
          transition: all 0.3s ease-out;  /* Chrome 26, Firefox 16+, IE 10+, Opera 12.10+ */
}

The previous snippet was copied and pasted from http://css3please.com

http://jsfiddle.net/ghodmode/6sE9E/

4

You can do this with only CSS using filter: brightness(); but it is only currently supported in WebKit browsers. See http://jsfiddle.net/jSyK7/

David Storey
  • 29,166
  • 6
  • 50
  • 60
2

You want to change the background-color lightness of any element that is hovered without using opacity. Unfortunately. I don't think this is possible without setting specific background-color values for your hovers.

The use case is that I'm allowing a user to hover over any element on a page. I don't want to go around determining each colors equivalent at 80% opacity.

There is one alternative that I can think of but it would require a translucent PNG overlay on the entire element, which will also cover any of the element's contents. Thereby not solving your problem.

Related Question: Dynamically change color to lighter or darker by percentage CSS (Javascript)

Community
  • 1
  • 1
Chris Bier
  • 14,183
  • 17
  • 67
  • 103