Is it possible to change only the alpha of a rgba background colour on hover?
Asked Answered
K

15

136

I have a set of <a> tags with differing rgba background colours but the same alpha. Is it possible to write a single css style that will change only the opacity of the rgba attribute?

A quick example of the code:

 <a href="#"><img src="" /><div class="brown">Link 1</div></a>
 <a href="#"><img src="" /><div class="green">Link 2</div></a> 

And the styles

a {display: block; position: relative}
.brown {position: absolute; bottom: 0; background-color: rgba(118,76,41,.8);}
.green {position: absolute; bottom: 0; background-color: rgba(51,91,11,.8);}

What I would like to do is write a single style that would change the opacity when the <a> is hovered over, yet keep the colour unchanged.

Something like

a:hover .green, a:hover .brown {background-color: rgba(inherit,inherit,inherit,1);}
Kopans answered 5/8, 2011 at 20:45 Comment(6)
By the way, what are your div elements doing in your a elements?Wader
@Wader HTML5 allows block-level a elements.Tetrahedron
@mercator: Alright. I missed that.Wader
@Wader It seemed the simplest way to code for the effect, a single a tag as opposed to one around the img and another around the text. The fact that it's supported by HTML 5 is a nice bonus.Kopans
When this question was asked - this wasn't possible with CSS. Now this is possible - with CSS Variables - as I've shown in my own answerZoolatry
Here's a link for those wondering how to convert RGB to RGBA.Thundersquall
W
83

This is now possible with custom properties:

.brown { --rgb: 118, 76, 41; }
.green { --rgb: 51, 91, 11; }

a { display: block; position: relative; }
div { position: absolute; bottom: 0; background-color: rgba(var(--rgb), 0.8); }
a:hover div { background-color: rgba(var(--rgb), 1); }

To understand how this works, see How do I apply opacity to a CSS color variable?

If custom properties are not an option, see the original answer below.


Unfortunately, no, you'll have to specify the red, green and blue values again for each individual class:

a { display: block; position: relative; }

.brown { position: absolute; bottom: 0; background-color: rgba(118, 76, 41, 0.8); }
a:hover .brown { background-color: rgba(118, 76, 41, 1); }

.green { position: absolute; bottom: 0; background-color: rgba(51, 91, 11, 0.8); }
a:hover .green { background-color: rgba(51, 91, 11, 1); }

You can only use the inherit keyword alone as a value for the property, and even then the use of inherit isn't appropriate here.

Wader answered 5/8, 2011 at 20:52 Comment(1)
Eagerly waiting for color modification functions (w3.org/TR/css-color-5) so we don't have to define the color channels as a list.Blondie
J
18

You could do various things to avoid having to hard code the numbers if you want to. Some of these methods only work if you use a plain white background as they're really adding white on top rather than reducing opacity. The first one should work fine for everything provided:

  • you aren't already using the psuedo-element for something; and
  • you can set position to relative or absolute on the <div> tag

Option 1: ::before psuedo-element:

.before_method{
  position:relative;
}
.before_method:before{
  display:block;
  content:" ";
  position:absolute;
  z-index:-1;
  background:rgb(18, 176, 41);
  top:0;
  left:0;
  right:0;
  bottom:0;
  opacity:0.5;
}
.before_method:hover:before{
  opacity:1;
}

Option 2: white gif overlay:

.image_method{
  background-color: rgb(118, 76, 41);
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/f/fc/Translucent_50_percent_white.png)
}
.image_method:hover{
  background-image:none;
}

Option 3: box-shadow method:

A variation of the gif method, but may have performance issues.

.shadow_method{
  background-color: rgb(18, 176, 41);
  box-shadow:inset 0 0 0 99999px rgba(255,255,255,0.2);
}
.shadow_method:hover{
  box-shadow:none;
}

CodePen examples: http://codepen.io/chrisboon27/pen/ACdka

Jardiniere answered 4/6, 2013 at 5:5 Comment(2)
Good answer, thanks. I found the third option useful and simpler if I reverse this method: don't use anything additional without hover, and on hover use: box-shadow: inset 0 0 0 99999px rgba(128,128,128,0.2). This was necessary for me because my rows alternate white and light gray, so the original answer didn't change the white.Pseudo
Liked the shadow method a lot.Cobwebby
T
13

No, it's not possible.

You could try a CSS pre-processor, though, if you want to do this sort of thing.

From what I could see, at least LESS and Sass have functions that can make colors more, or less, transparent.

Tetrahedron answered 5/8, 2011 at 21:3 Comment(2)
I always forget about SCSS/LESS. Always. Maybe I need to start actually using them.Wader
In SCSS, it is transparentize([color], 0.8). See sass-lang.com/documentation/Sass/Script/…Baptiste
Z
9

It's now 2017 and this is now possible with

CSS custom properties / CSS Variables (Caniuse)

One classic use case for CSS variables is the ability to individualize parts of a property's value.

So here, instead of repeating the whole rgba expression once again - we split up or 'individulaize' the rgba values into 2 parts / variables (one for the rgb value and one for the alpha)

.brown { 
  --rgb: 118, 76, 41; 
}
.green {
  --rgb: 51, 91, 11;
}
.brown, .green {
  --alpha: 0.3;
  background-color: rgba(var(--rgb), var(--alpha));
}

Then, on hover we can now just modify the --alpha variable:

a:hover .green, a:hover .brown {
  --alpha: 1;
}

a {
  display: block;
  position: relative;
}
.brown { 
  --rgb: 118, 76, 41; 
}
.green {
  --rgb: 51, 91, 11;
}
.brown, .green {
  display: inline-block;
  --alpha: 0.3;
  background-color: rgba(var(--rgb), var(--alpha));
  font-size: 40px;
  margin: 20px;
}

a:hover .green, a:hover .brown {
  --alpha: 1;
}
<a href="#">
  <div class="brown">Link 1</div>
</a>
<a href="#">
  <div class="green">Link 2</div>
</a>

Codepen

Further reading:

Individualizing CSS Properties with CSS Variables (Dan Wilson)

Zoolatry answered 2/8, 2017 at 14:25 Comment(0)
T
6

No, that's not possible.

If you want to use rgba, you must set each value together. There's no way to only change the alpha.

Thumbtack answered 5/8, 2011 at 20:52 Comment(0)
D
6

there is an alternative,you can add a linear-gradient background image onto the original color.

a{
  background: green
}
a:hover{
  background-image:linear-gradient(hsla(0,0%,0%,.2) 100%,transparent 100%) // darker
}
a:hover{
  background-image:linear-gradient(hsla(255,100%,100%,.2) 100%,transparent 100%) // lighter
}

also, with css3 filter property,you can do that too,but it seems that it will change the text color

a:hover{
   filter: brightness(80%) //darker
}
a:hover{
   filter: brightness(120%) //lighter
}

here is a jsfiddle:https://jsfiddle.net/zhangyu911013/epwyL296/2/

Declamatory answered 13/6, 2017 at 7:40 Comment(2)
so far the only satisfying answer for me.Malathion
Agree with Andre. Can be further simplified with use of css variables. Have added an answer to clarify.Lin
A
4

Why not use :hover and specify a different opacity in the hover class?

a:hover {
     opacity:0.6
}
Agneta answered 5/8, 2011 at 20:51 Comment(4)
Because that affects the whole element.Wader
with SVG objects, it's possible to use fill-opacityKelt
not only the whole element, but all child elements as well.Ichthyolite
Not perfect perhaps, but it is useful for some cases.Catheryncatheter
S
2

I had a similar problem. I had 18 different divs working as buttons, and each with a different color. Rather than figure out the color codes for each or use a div:hover selector to change the opacity (which affects all children) I used the pseudo-class :before like in @Chris Boon's answer.

Because I wanted to do the coloring on the individual elements, I used :before to create a transparent white div on :hover. This is a very basic washout.

#categories div {
    position:relative;
    width:100px;
    height:100px;
    float:left;
    border:1px solid black;
    display:table-cell;
}

#categories div:before{
    content:"";
    position:absolute;
    top:0px;
    left:0px;
    width:100px;
    height:100px;
}

#categories div:hover:before {
    background-color:white;
    opacity:0.2;
}

#a_Particular_Div {
    background-color:red;
}

According to CanIUse.com, this should have something like 92% support as of early 2014. (http://caniuse.com/#feat=css-gencontent)

Scevour answered 31/1, 2014 at 17:9 Comment(0)
D
2

You can do this with CSS variables, although it's a little messy.

First, set a variable containing just the RGB values, in order, of the color you want to use:

:root {
  --color-success-rgb: 80, 184, 60; 
}

Then you can assign an RGBA value for a color and pull everything but the alpha value from this variable:

.button--success {
  background: rgba(var(--color-success-rgb), 0.8);
}

This isn't super pretty, but it lets you use the same RGB values but different alpha values for a color.

Dallis answered 5/5, 2017 at 13:15 Comment(1)
This is a reasonable solution to the problem. And, the variable with color doesn't have to be on :root, it can be on the class of element, setting its base color. Thanks!Natator
D
2

simple solution :

a
{
    position: relative;
    display:inline-block;
    background: rgba(red, 0.75);
    padding: 20px;


   &:before
   {
     content: ' ';
     position: absolute;
     left: 0;
     top: 0;
     width: 100%;
     height: 100%;
   }

   &:hover
   {
     &:before
     {
       background-color: rgba(#000, 0.25); 
     }
   }
}

exemple : https://jsfiddle.net/epwyL296/14/

just play with alpha of background. if you want light instead of darkness, just replace #000 by #fff

Dividend answered 28/2, 2018 at 10:48 Comment(0)
E
1

Update: It's not possible to do that unfortunately. You'll need to write two separate selectors of:


a.green:hover {background-color: rgba(118,76,41,1);}
a.brown:hover {background-color: rgba(118,76,41,1);}

According to the W3C, the rgba property doesn't have/support the inherit value.

Epiphysis answered 5/8, 2011 at 20:48 Comment(4)
The issue is that inherit isn't a valid function argument. You'll notice it doesn't work with any other CSS function.Wader
By function do you mean things like rgba and transitions? Because I know it's supported with quite a few of the properties.Epiphysis
Yup, along with url(), attr() etc too. inherit is a property value only.Wader
I knew about url() and transitions already. I just wasn't 100% sure on rgba because it's used for colours. Thank you for educating me though :)!Epiphysis
O
1

I faced a similar problem. Here's what I did and it works fine( only alpha changes on hover and also the text is not affected) by the following steps:

1) Apply a highlighted(or any of your choice) class to whichever element you wish to change background alpha of.

2) Get the background color rgba

3) Store it in a string and manipulate it(change alpha) as you want on hover(mouseenter and mouseleave)

HTML Code:

<div class="highlighted brown">Link 1</div><br><br>
<div class="highlighted green">Link 1</div>

CSS Code:

.brown {background-color: rgba(118,76,41,.8);}
.green {background-color: rgba(51,91,11,.8);}

Javascript Code:

$(document).on({

            mouseenter: function() {

            var rgba_str = $(this).css("background-color");
            var new_rgba_str ="rgba(" + rgba_str.substring(rgba_str.lastIndexOf("(")+1,rgba_str.lastIndexOf(",")) + ", 0.5)";   

                $(this).css("background-color",new_rgba_str ); 
               },

             mouseleave: function(){

                 var rgba_str = $(this).css("background-color");

            var new_rgba_str ="rgba(" + rgba_str.substring(rgba_str.lastIndexOf("(")+1,rgba_str.lastIndexOf(",")) + ", 0.8)";               
                $(this).css("background-color",new_rgba_str ); 

               }

        },'.highlighted');

Working Fiddle:http://jsfiddle.net/HGHT6/1/

Oscillation answered 8/7, 2014 at 12:4 Comment(0)
G
0

Simple workaround with opacity if you can accommodate a slight change in background-color:

.yourClass {
    // Your style here //
    opacity: 0.9;
}

.yourClass:hover, .yourClass:focus {
    opacity: 0.7;
}

.yourClass:active {
    opacity: 1;
    box-shadow: none;
}

.yourClass:hover, .yourClass:focus, .yourClass:active {
    text-decoration: none;
    outline: none;
}
Gargoyle answered 24/7, 2018 at 16:27 Comment(0)
L
0

Building on Yu Zhang's answer:

In :root, (or parent component in Blazor) set css variables:

--bg-img-light: linear-gradient(hsla(255,100%,100%,.2) 100%, transparent 100%);
--bg-img-dark: linear-gradient(hsla(0,0%,0%,.2) 100%, transparent 100%);

Then on any element that you want to apply a hover effect on:

.buttontomakelighter:hover {
  background-image: var(--bg-img-light);
}

.buttontomakedarker:hover {
  background-image: var(--bg-img-dark);
}
Lin answered 8/5, 2021 at 19:32 Comment(0)
N
-5

This is about the simplest way; put this in your css stylesheet:

a:hover { color : #c00; } 

done!

Nucleotide answered 5/8, 2011 at 20:52 Comment(2)
-- just match the color to something close. opacity does not work in all browsers.Nucleotide
Your answer has a nice trick, but your comment is totally irrelevant.Wader

© 2022 - 2024 — McMap. All rights reserved.