Make a parent div webkit-filter not affect children

little tiny man picture little tiny man · Mar 22, 2014 · Viewed 22.2k times · Source

I'm using a very fancy webkit filter to make background-images grayscale, and on hover over the images become color.

Here's the filter

filter: none;
-webkit-filter: grayscale(0);
transition: opacity .3s ease-in-out;
-moz-transition: opacity .3s ease-in-out;
-webkit-transition: opacity .3s ease-in-out;

As you can see, there's even a 'transition' property so that the image has a smooth fading transition into full color. The problem that I'm having is that the div I'm applying it to is also affecting the child text positioned inside the div, turning the text into grayscale as well. This is a problem because the text needs to be white, even when not being hovered over.

I've tried negating the filter with another one on the child text but it doesn't seem to work... Check out the fiddle

Fiddle http://jsfiddle.net/yMHm4/1/

Answer

vals picture vals · Mar 23, 2014

This is not a problem of properties inheritance, as you can think.

The way filters work makes that imposible to fix changing attributes in the CSS: The element affected by the filter is rendered, all the children are rendered, and then the result (as an image) has the filter applied.

So the only alternatives left are:

1) Change the HTML, as Lowkase suggested

2) In your case, seems that all you want to make gray is the background image. In this case, you can leave the HTML as is, display the image in a pseudo element, and apply the filter to this pseudo element.

CSS

.cell{
    opacity:0.7;
    width:420px;
    height:420px;
    transition: opacity .3s ease-in-out;
    -moz-transition: opacity .3s ease-in-out;
    -webkit-transition: opacity .3s ease-in-out;
}

.A1 {
    position: relative;
}
.A1:before {
    content: "";
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    background-image:url('http://i.imgur.com/NNKxZ5R.jpg');
    filter: url(filters.svg#grayscale); /* Firefox 3.5+ */
    filter: gray; /* IE6-9 */
    -webkit-filter: blur(15px); /* Google Chrome, Safari 6+ & Opera 15+ */ 
    z-index: -1;
}

#text {
    color:#ffffff;
    text-align:center;
    font:18px sans serif;
    text-decoration:none;
}
.cell:hover {
    opacity:1.0;
}

.A1:hover:before {
    filter: none;
    -webkit-filter: grayscale(0);
    transition: opacity .3s ease-in-out;
    -moz-transition: opacity .3s ease-in-out;
    -webkit-transition: opacity .3s ease-in-out;
}

fiddle

I have also changed your filter to blur to make it more clear the the text is not affected by the filter. Since you had also some opacity set, the text still looked grayish just because you were seeing the gray under it.

Added example using brightness filter (for webkit)

demo 2