Search code examples
csssvgbackground-imagemaskcss-transforms

SVG with mask as background-image of HTML element


I want to use an SVG as the background-image of an HTML element. However, this fails when I use a mask anywhere in the SVG. When mask="url(#m)" is removed in the code below, the SVG is displayed as the background image without issue.

HTML:

<div>Some element.</div>

JavaScript:

// The following SVG is correctly rendered as a standalone SVG file, but not in `background-image`.
const svg = `<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
  <mask id="m" maskContentUnits="objectBoundingBox">
    <rect fill="white" x="0" y="0" width="100%" height="100%" />
  </mask>
  <rect mask="url(#m)" width="100" height="100" fill="red" />
</svg>`;

document.querySelector("div").style.backgroundImage = `url(data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;

(JSFiddle link)

Result: no background image

Expected result: intended background image

Is it possible to have SVG masks in a background-image like this? If not, what's the reason?

Relatedly, the background image also fails to display if I add style="transform: translate(0)" to the svg (though other styles, like style="background-color: blue" work without issue). Is it possible to use transform in an SVG background-image?


Solution

  • Your syntax is wrong for the data URL

    document.querySelector("div").style.backgroundImage = `url('data:image/svg+xml,${encodeURIComponent(svg)}')`;
    

    is what you want

    const svg = `<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
      <mask id="m" maskContentUnits="objectBoundingBox">
        <rect fill="white" x="0" y="0" width="100%" height="100%" />
      </mask>
      <rect mask="url(#m)" width="100" height="100" fill="red" />
    </svg>`;
    
    document.querySelector("div").style.backgroundImage = `url('data:image/svg+xml,${encodeURIComponent(svg)}')`;
    <div>Some element.</div>