Search code examples
svgsvg-filters

How to fill a shape with the inverse of its background in SVG?


How to create a shape, e.g. a rectangle, that inverts (xor?) all colors behind it?

Unsuccessfully I tried:

<filter
id="invert">
<feColorMatrix
in="BackgroundImage"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "/>
<feComposite
operator="in"
in2="SourceGraphic"/>
</filter>
<svg>
  <rect x="10" y="10" width="50" height="50" fill="blue"></rect>
  <rect x="20" y="20" width="50" height="50" fill="blue" style="filter: url(#invert);"></rect>
</svg>

http://codepen.io/anon/pen/bqXPPZ


Solution

  • BackgroundImage is an unsupported input for almost all browsers and is officially deprecated in the next Filters spec.

    Your alternatives are:

    • Take a copy of whatever's in the background image and import it into a filter using feImage so you can use it
    • Use the non-standard CSS backdrop-filter: invert(100%) - only supported in recent webkit (aka not Chrome)
    • Use CSS background-blend and mix-blend (recent browsers only) example:

    .content {
      background-image: url("http://stylecampaign.com/blog/blogimages/SVG/fox-1.svg");
      background-size: 600px; 
      position: absolute;
      top: 40px;
      left: 30px;
      width: 700px;
      height: 800px;
    }
    
    .inverter {
      background: white;
      position: absolute;
      top: 200px;
      left: 300px;
      width: 300px;
      height: 100px;
      mix-blend-mode: exclusion;
    }
    <div class="content">
      <div class="inverter"/>
    </div>

    • Your last option is to layer the original content below the inverted version of your contents using an inversion SVG filter and then use a mask on the inverted version to crop to the desired shape.

    <svg width="800px" height="600px">
      <defs>
        <filter id="invert">
          <feComponentTransfer>
            <feFuncR type="table" tableValues="1 0"/>
            <feFuncG type="table" tableValues="1 0"/>
            <feFuncB type="table" tableValues="1 0"/>
            </feComponentTransfer>
        </filter>
        
         <mask id="mask-me">
          <circle cx="215" cy="180" r="100" fill="white" />
        </mask>
      </defs>
      
        <image width="400" height="400" x="20" y="20" xlink:href="http://stylecampaign.com/blog/blogimages/SVG/fox-1.svg" />
      <image width="400" height="400" x="20" y="20" filter="url(#invert)" xlink:href="http://stylecampaign.com/blog/blogimages/SVG/fox-1.svg" mask="url(#mask-me)"/>
    
    </svg>