0

I have several buttons with different background images. I would like to achieve to have a grayscale filter on them by default and on hover remove the grayscale filter.

I have this already but the problem is that the text of the buttons are also grayed out which i would like to avoid. I Couldn't figure out how to apply grayscale filter only on button backgrounds but not on text.

Now I have a main css class for the buttons

.box {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
position:relative;
color: red;
cursor:pointer;
text-align: center;
width: 160px;
height: 160px;
}
.box:hover {
-webkit-filter: grayscale(0%);
filter: grayscale(0%);
color: blue;
}

and I apply the backgrounds for each button in html code

<button onclick="buttonFunction()" button class="button box" style="background: url(background1.jpg); background-size: 100%;" >Gray button text:( </button>

Any idea how to add grayscale filter only button backgrounds and keep the button texts colored?

Thanks

Nartaas
  • 3
  • 1
  • 4

2 Answers2

0

As Temani Afif also points out pseudo elements are your way to go although I would like to add a bit different way of positioning which I believe might be more precise and more easy to adapt to a responsive design.

The key part is making the .box have the same height and line-height which will also be the height of our :after content. Then the absolute positioning (0-0-0-0) will center it automatically.

.box {
  position: relative;
  color: #ff0000;
  text-align: center;
  width: 300px;
  height: 300px;
  line-height:300px;
}

.box:before {
  content: ' ';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  filter: grayscale(100%);
  background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/16777216colors.png/220px-16777216colors.png);
  background-size: cover;
}

.box:hover:before {
  filter: grayscale(0%);
}

.box:after {
  content: 'Text Text Text';
  position: absolute;
  left:0;
  bottom:0;
  right:0;
  top:0;
  display: inline-block;
  vertical-align: middle;
}
  <button type="button" class="box">Button</button>  
Andrew Adam
  • 1,572
  • 9
  • 22
  • In your case no need to specify the height on after element. Using top/bottom is enough. Also you are not applying your style on the button but on a container of the button. It will be confusing as we can no more click on the button which make it useless – Temani Afif Nov 03 '17 at 08:44
  • @TemaniAfif you are absolutely right! The height I left there since older IE can act up with not-fixed height pseudo but the button-clicking would have been a very bad loss. Great catch, thanks a lot! – Andrew Adam Nov 03 '17 at 08:55
0

Applying the filter property to an element will affect the children of that element. You will not be able to unset / reset the filter property for the children.

If you don't want to / can't use the pseudoelement approach in the other answers, then you could change your HTML to create the effect you want.

Add the image as an img element in the button, and place the text in a span. You can then apply the filter to the img.

.box {
  cursor: pointer;
  width: 160px;
  height: 160px;
  position: relative;
  padding: 0;
  display: inline-flex;
  justify-content: center;
  align-items: center;
}

.box img {
  -webkit-filter: grayscale(100%);
  filter: grayscale(100%);
  position: absolute;
  max-width: 100%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

.box:hover img {
  -webkit-filter: grayscale(0%);
  filter: grayscale(0%);
}

.text {
  color: red;
  z-index: 1;
}

.box:hover .text {
  color: blue;
}
<button onclick="buttonFunction()" button class="button box"><img src="https://unsplash.it/200x200"><span class="text">Gray button text:(</span></button>
sol
  • 22,311
  • 6
  • 42
  • 59