cssbackground-imagemix-blend-modeimage-masking

Mix blend mode not working on text in css


I'm trying to apply mix-blend-mode: screen to create a "clipped" background. It's working fine with an overlay image.

But when I apply it on a text, it does not work.

With img (working):

body {
  margin: 0;
}

div {
  height: 100vh;
}

img {
  position: absolute;
  width: 100%;
  height: 100%;
}

.clip {
  mix-blend-mode: screen;
}
<div>
  <img src="https://images.unsplash.com/photo-1625252568254-256958377c1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80">
  <img class='clip' src="https://images.unsplash.com/flagged/photo-1585745540837-ec55409a515d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1414&q=80">
</div>

With text (Not working):

body {
  margin: 0;
}

div {
  height: 100vh;
}

img {
  position: absolute;
  width: 100%;
  height: 100%;
}

span {
  position: absolute;
  font-size: 200px;
}

.clip {
  mix-blend-mode: screen;
}
<div>
  <img src="https://images.unsplash.com/photo-1625252568254-256958377c1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80">
  <span class='clip'>Text</span>
</div>


Note: I don't want to use a background image and clip it with text as the background is supposed to be dynamic (instead of the static image here).

body {
  margin: 0;
}

div {
  font-size: 200px;
  font-weight: bold;
  background-image: url('https://images.unsplash.com/photo-1625252568254-256958377c1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80');
  background-position: center;
  color: transparent;
  background-clip: text;
}
<div>
  Text
</div>


Solution

  • Using mix-blend-mode:

    If the background is white, you can use mix-blend-mode: color-dodge; by setting a white element with black text on top of the images:

    body {
      margin: 0;
    }
    
    div {
      height: 100vh;
    }
    
    img {
      position: absolute;
      width: 100%;
      height: 100%;
    }
    
    .clip {
      mix-blend-mode: screen;
    }
    
    .text {
      position: absolute;
      inset: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      
      font-size: 200px;
      background: white;
      color: black;
      
      mix-blend-mode: color-dodge;
    }
    <div>
      <img src="https://images.unsplash.com/photo-1625252568254-256958377c1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80">
      <img class='clip' src="https://images.unsplash.com/flagged/photo-1585745540837-ec55409a515d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1414&q=80">
      
      <div class="text">Text</div>
    </div>

    Using background-clip:

    Convert the images to the div's background, and use background-blend-mode: screen; to blend them, and background-clip: text; to clip them by the text:

    body {
      margin: 0;
    }
    
    div {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      max-width: 500px;
      background: url(https://images.unsplash.com/photo-1625252568254-256958377c1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80), url(https://images.unsplash.com/flagged/photo-1585745540837-ec55409a515d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1414&q=80) no-repeat;
      background-size: contain;
      background-blend-mode: screen;
      background-clip: text;
      color: transparent;
      font-size: 200px;
    }
    <div>Text</div>