skyisred
skyisred

Reputation: 7105

Greyscale background image, but not content

I tried using this technique

<div class="grayscale"><span style="color:red">Red Text</span>

 .grayscale {
     background: url(yourimagehere.jpg);
     -moz-filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");
     -o-filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");
     -webkit-filter: grayscale(100%);
     filter: gray;
     filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");
 }

It works well on background image, but also greys out all contents of the box. Is there any way to grey background only but keep contents full color? Thanks!

fiddle

Upvotes: 3

Views: 3587

Answers (3)

oliver_siegel
oliver_siegel

Reputation: 1676

It's possible, as seen here

You'll need to make your background image as the :before element, then the greyscale filter won't be applied to the children.

HTML

<div class="module">
  <div class="module-inside">
    Module
  </div>
</div>

CSS

body {
  height: 100vh;
  padding: 0;
  display: grid;
  align-content: center;
  justify-content: center;
}
.module {
  width: 300px;
  height: 300px;
  display: grid;
  place-items: center;
  color: #ff43ea;
  position: relative;
}
.module::before {
  content: "";
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  position: absolute;
  background-image: url(https://images.unsplash.com/photo-1494645009625-cc17363a5f20?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ&s=bd502af39c922553e5a13624d4f44f40);
  background-size: cover;
  filter: grayscale(100%);
}
.module-inside {
  position: relative;
  font: bold 42px sans-serif;
}

Example: https://codepen.io/chriscoyier/pen/GXeQyJ

Upvotes: 1

Pere
Pere

Reputation: 1075

It's almost what @chris said. Taken from http://dev.w3.org/fxtf/filters/:

A computed value of other than none results in the creation of a stacking context [CSS21] the same way that CSS opacity does. All the elements descendants are rendered together as a group with the filter effect applied to the group as a whole.

You can, for instance, take the text out of your div and place it with absolute positioning.

Upvotes: 0

chris
chris

Reputation: 1184

You are applying the greyscale to the entire div with the class greyscale. This means that everything inside the div will comply. Therefore, you need to take your content (the span) out of the greyscale div and use css positioning to overlay the content on the image.

Upvotes: 0

Related Questions