How do I limit a blended overlay to its parent content?

I may not fully understand CSS’s ‘isolation’ attribute, however let me describe the hierarchy simply (https://jsfiddle.net/8zq7r23u/2/).

<svg>
 [shapes filled with grayscale]
  |
  -> [some kind of tint shape with a blend mode] -- to colourize its parents

What is happening is if the SVG is placed on a gray background, the background is affected by the blended item. I do not want this. I want the colourizing layer to only affect the SVG.

Normally what I do in your standard raster desktop applications (or vector for that matter), is I apply a mask. I’ve come to this point to ask if it’s possible without the mask, or am I doing something wrong entirely?

Answer

The isolation property creates a new stacking context for the blending modes you have applied, so any child elements will only blend up to the element set to isolate.

In your case you can simply set isolation: isolate; on the SVG itself (since your background is outside of the SVG).

As a quick example take this SVG, which looks something like this (cut down for brevity):

<svg>
    <style>
        #text { mix-blend-mode: screen; }
    </style>
    <image xlink:href="background.jpg"></image>
    <g id="blend-group">
        <rect fill="#FF0000" ... />
        <rect fill="#0042D3" ... />
        <path id="text" fill="#1061FF" ... />
    </g>
</svg>

Which is rendered as this:

SVG blending

Now, if we change our style block to this:

<style>
    #blend-group { isolation: isolate; }
    #text { mix-blend-mode: screen; }
</style>

We get this:

SVG isolated blending

Notice how the text doesn’t blend with the image, but does still blend with the rectangles. This is because we created a new context for #blend-group, so anything set to blend within that group will only blend within that group.

There is a good (probably better) explanation and example of isolation being used in this CSS Tricks article:

If you not only want to limit the blending but hide the layer outside of that context too then you’ll need to define a clipping path. You do this by defining a clipPath element and referencing it in your CSS with the clip-path property. Which would look something like this:

<style>
    #text {
      mix-blend-mode: screen;
      clip-path: url(#clip);
    }
</style>
<defs>
    <clipPath id="clip">
        <rect id="rect" ... />
    </clipPath>
</defs>

We then get this:

SVG ClipPath clipping

An more in depth run down of various CSS clipping methods can be found here:

Attribution
Source : Link , Question Author : chrisp , Answer Author : Cai

Leave a Comment