pythoncsssvgpycairo

SVG Fill available space in nested elements


I am generating a SVG with nested elements. For the styling of the elements, there needs to be separate fill colours with opacity for the parent container and child elements. However, due to opacity, the colours overlap and it is not a clean result. Is there a way to fill only the space not occupied by child elements in the parent container

I am looking for an equivalent of the polygon evenodd fill rule but for nested elements

enter image description here


Solution

  • You can do this with a mask and a filter. The filter creates an image from the children, where all pixels that are not fully transparent become black and all fully transparent pixels become white. The result of the filter and a white rectangle that covers all the area that the child does not cover is then applied as a mask.

    #parentElement {
      fill: rgba(204, 41, 41, 0.3);
    }
    
    #childElement {
      fill: green;
      opacity: 0.2;
    }
    <svg width=400 height=400>
      <defs>
        <filter id="mask-filter">
          <feComponentTransfer>
            <feFuncA type="linear" slope="255" intercept="0"></feFuncA>
          </feComponentTransfer>      
          <feColorMatrix type="matrix"
              values="0 0 0 -1 1
                      0 0 0 -1 1
                      0 0 0 -1 1
                      0 0 0 0 1" />
        </filter> 
        <mask id="mask1">
          <rect x="0" y="0" width="100%" height="100%" fill="white" />
          <use xlink:href="#childElement" filter="url(#mask-filter)" />
        </mask>
      </defs>
      <rect id="parentElement" x=10 y=10 width=140 height=100 mask="url(#mask1)" />
      <rect id="childElement" x=60 y=40 width=240 height=140 />
    </svg>