skip to Main Content

I am trying to create a CSS container that has a red overlay with dynamically assigned with using javascript.

The problem is I need to change the color of text which is overlapping red background to white while keeping the other part still black.

I found plenty of solutions to invert colors using mix-blend-mode: difference property, but this makes the non-overlapping text matching the color of the background which is not what I want.

Here is the closest example that I could achieve.

https://jsfiddle.net/L9yw62p4/7/

2

Answers


  1. You just need to change this code:

    .text {
      position: relative;
      mix-blend-mode: difference;
      color: aqua;
    }
    

    To:

    .text {
      position: relative;
      mix-blend-mode: darken;
      color: aqua;
    }
    

    This will make 60% of the text black and the other 40% text color aqua.

    Login or Signup to reply.
  2. Addressing this part of your question:

    The problem is I need to change the color of text which is overlapping
    red background to white while keeping the other part still black.

    If I understand correctly you have a piece of text that you wish to be coloured as absolute white (regardless of any blending) in the region where it’s overlapping the .bg element background and to be coloured as black otherwise. I’m not perfectly sure then why in your code snippet you have the text coloured as aqua then.

    Since you are not strictly dealing with colour blending but you want to replace the overlapping colour with a fixed one (white), the only solution I can come up with is just having two perfectly equal text lines. One of those will be nested inside the .bg element (and cropped) while the other one won’t.

    The colour driving the text based on the overlapping condition is set inside two css variables.

    .container {
      border: 1px solid black;
      position: relative;
      height: 1em;
      width: 300px;
      
      --overlapping: white;       /*text color when overlapping*/
      --nonoverlapping: black;    /*text color when non overlapping*/
    }
    
    .bg {
      background: #AD3435;
      width: 60%;
      height: 100%;
      overflow: hidden;
      position: absolute;
    }
    
    .nonoverlapping-text, .overlapping-text {
      position: absolute;
      top: 0;
    }
    
    .nonoverlapping-text {
      color: var(--nonoverlapping);
      z-index: 1;
    }
    
    .overlapping-text {
      color: var(--overlapping);
      z-index: 2;
    }
    <div class="container">
      <div class="bg">
        <div class="overlapping-text">ABCABCABCABCABCABCABCABCABC</div>
      </div>
      <div class="nonoverlapping-text">ABCABCABCABCABCABCABCABCABC</div>
    </div>

    And this is a second version of the same approach that strips down the complexity to the bare minimum hiding the details by using pseudo-elements and data attributes:

    .masked{
      position: relative;  
      border: 1px solid black;  
      display: inline-block;  
      
      /*sets a static width instead to just fit to the content*/
      /*width: 300px;*/ 
    }
    
    .masked::before{
      position: absolute;
      top: 0;  
      height: 100%;    
      overflow: hidden;            
      
      background: #AD3435;        
      width: var(--fill);
      content: attr(data-content);
      color: white;
    }
    
    .masked::after{  
      content: attr(data-content);
      color: black;
    }
    <div class="masked" data-content="ABCABCABCABCABCABCABCABCABC" style="--fill:60%;"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search