Carl
Carl

Reputation: 113

"Selective masking" with SVG element beneath and body background

I'm working on a page right now where two div classes, one big relative positioned. And the other absolute which I have placed on different X,Y positions on the web page. The absolute div have a SVG background which have a opacity in the middle.

Although the problem is when the absolute div is on top the relative one, it's also showing the relative div underneath through the opacity which is an unwanted result.

My question is, is somehow "selective masking" possible with CSS/SVG. Or would there be any other creative way to solve it? I've tried a lot of searching but I haven't really found any valuable information.

See the image for example:

example image

Upvotes: 1

Views: 323

Answers (2)

Michael Mullany
Michael Mullany

Reputation: 31715

You can do it with a filter, if you're prepared to put everything in SVG and have the flexibility to use colors as green screens, but it's a bit hinky:

codepen: http://codepen.io/mullany/pen/sogvi?editors=101

svg{
background-image: url("http://slowbuddy.com/wp-content/gallery/plain-background/cool-background-textures-ha_textures.jpg");
}
<svg>
  <defs>
  <filter id="knockoutSpecial">
    <!--pulls the offscreen text- "Cutting Out Text" into the filter region so we can use it -->
    <feOffset dy="150" dx="0" result="pos-text">
      <animate attributeName="dx" values="0;300;0" dur="6s" repeatCount="indefinite"/>
    </feOffset>
    <!--uses "out" to knock out the overlapping areas" -->
    <feComposite operator="out" in2="SourceGraphic" in="pos-text" result="cut-red"/>
     <!-- uses only the offset term to discard original text color and change to our desired color -->   
    <feColorMatrix in="cut-red" result="recolor1" type="matrix" values="0 0 0 0 1
                          0 0 0 0 0.0
                          0 0 0 0 0.1
                          0 0 0 1 0"/>    
   <!-- discards our green-screen fill, setting any green to a very low opacity using the -5" -->   
    <feColorMatrix in="SourceGraphic" result="empty-red" type="matrix" values="1 0 0 0 0
                          0 1 0 0 0
                          0 0 1 0 0
                          0 -5 0 1 0"/>
   <!-- uses only the offset term to discard original text stroke color and it to our desired color -->   
    <feColorMatrix in="empty-red" result="recolor2" type="matrix" values="0 0 0 0 0.5
                          0 0 0 0 0.5
                          0 0 0 0 0.5
                          0 0 0 1 0"/>
  <!-- superimposes our cut out text and our now empty text both at their correct color -->   
    <feComposite operator="over" in="recolor1" in2="recolor2"/>
  </filter>
  </defs>
  
  <g filter="url(#knockoutSpecial)">
      <!-- uses pure red, green and blue colors purely for pixel selection in the filter - the content is recolored in the filter. Also positions part of our text off screen. We'll bring that back with our first filter term. -->  
    <text x="0" y="-50" font-size="84" font-weight="bold" fill="red">Cutting out text?</text>
    <text stroke="blue" stroke-width="2" fill="green" x="40" y="120" font-size="84" font-weight="bold" font-family="helvetica">No Problem....</text>
    
  </g>
  
  
</svg>

Upvotes: 1

James Montagne
James Montagne

Reputation: 78650

This is doable with clip-path. However, don't believe this will work in FF or IE.

The idea is to use clip-path to cut out a section of the under div which corresponds to the size and location of the overlapping area. If the divs move, this may need to be updated via js but if the relative positions are static, you can just create the css once and you're all set.

http://jsfiddle.net/tL3gxtjw/

body {
  background-color: yellow;
}
#under {
  position: relative;
  top: 25px;
  left: 25px;
  height: 200px;
  width: 200px;
  background-color: blue;
  border: 3px solid red;

  -webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 0 115px, 30px 115px, 30px 70px, 0 70px);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 0 115px, 30px 115px, 30px 70px, 0 70px);
}
#over {
  height: 40px;
  width: 40px;
  border: 5px solid green;
  position: absolute;
  top: 100px;
  left: 15px;
  ;
}
<div id="under"></div>
<div id="over"></div>

Upvotes: 1

Related Questions