3
votes

I'm attempting to use an SVG image as a css background image. The SVG(s) in question will ultimately use a number of large JPEG images (embedded or linked) as a mask for other SVG elements. I'm doing this instead of using PNGs for the file size savings. (my highly compressed grayscale jpegs are tiny)

Currently I can only get embedded base64 encoded images to display properly and Safari just doesn't work (aside from using embed to show the SVG directly)

The following is my testing code:

(All images are from archive.org and links should be persistent - I've omitted the base64 encoded data)

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="application/xhtml+xml">
    <style type="text/css">
      body { font-family: Arial, sans; }
      .box1, .box2, .box3 { width: 400px; height: 100px; background-size: 192px 192px; margin: 10px 10px 0px 0px; padding: 10px; }
      .box1 { background: url("test1.svg"); }
      .box2 { background: url("test2.svg"); }
      .box3 { background: url("test3.svg"); }
      .sml { width: 100px; height: 100px; margin: 10px 10px 10px 0px; }
    </style>
  </head>
  <body>
    <div class="box1">Test 1</div>
    <div class="box2">Test 2</div>
    <div class="box3">Test 3</div>
    <img class="sml" src="test1.svg" type="image/svg+xml">
    <img class="sml" src="test2.svg" type="image/svg+xml">
    <img class="sml" src="test3.svg" type="image/svg+xml">
    <embed class="sml" src="test1.svg" type="image/svg+xml">
    <embed class="sml" src="test2.svg" type="image/svg+xml">
    <embed class="sml" src="test3.svg" type="image/svg+xml">
  </body>
</html>

working embedded image SVG

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns:cc="http://web.resource.org/cc/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  x="0px" y="0px" width="192px" height="192px" viewBox="0 0 192 192">
  <style type="text/css" id="style_css_sheet">
    .orange { fill: #f9690e; }
    .yellow { fill: #f1d40f; }
  </style>
  <defs>
    <filter id="invert">
      <feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
    </filter>
    <rect id="box-bg" x="0" y="0" width="192px" height="192px" class="yellow" />
    <rect id="box-fg" x="0" y="0" width="192px" height="192px" class="orange" />
    <mask id="fg-mask" x="0" y="0" width="192px" height="192px" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
      <image id="mask-img" width="192px" height="192px" filter="url(#invert)"
        xlink:href="data:image/jpg;base64,
        [[ DATA ]]"></image>
    </mask>
  </defs>
  <use xlink:href="#box-bg" overflow="visible"></use>
  <use xlink:href="#box-fg" mask="url(#fg-mask)" overflow="visible"></use>
</svg>

broken?? image xlink variant

  <mask id="fg-mask" x="0" y="0" width="192px" height="192px" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
    <image id="mask-img" width="192px" height="192px" filter="url(#invert)" xlink:href="http://bit.ly/1u61zrE"></image>
  </mask>

So... Safari only likes the embed tags, chrome and firefox can do the background but only when the image is embedded as data. Any ideas on how to get Safari working, at least with the embedded data would be great. If there's a way to get them all working, even better...

Thanks.

2
For privacy reasons SVG-as-an-image must be complete in one file see longsonr.wordpress.com/2013/10/23/… for more details. - Robert Longson
Thanks Robert - this describes what I thought was happening behind the scenes. I would then surmise that Safari doesn't yet support part of what I'm doing as well as I haven't been able to use my SVGs as a background image on safari in any scenario. (embedded or linked images) - rjmoggach
For anyone answering this question, I'll accept the answer when there's a working solution - As Robert has pointed out it may not be available (yet) although I'm open to javascript workarounds that aren't page specific. Eg. It'd be nice if something like modernizr provided this by pre-rendering and inserting into the DOM for browsers that don't support it. (ie. all of them??) - rjmoggach
If you're waiting till external image data is supported in SVG-as-an-image you'll be waiting forever. - Robert Longson
Robert can you add that as an answer and I'll accept it - rjmoggach

2 Answers

3
votes

For privacy reasons SVG-as-an-image must be complete in one file. Browsers will never support external references in SVG-as-an-image. The basic premise is that you can only do things with SVG-as-an-image that you could do with a raster image.

If you need external references use <object> or <iframe>

0
votes

As Robert Longson mentions, browsers will not load external files referenced from SVGs used as images (HTML <img> or CSS background images).

<embed> tags should work, with the entire SVG and linked images loaded. However, <embed> have only become standardized recently, so there may be some inconsistencies. To ensure the greatest support, use a mix of <object> tags and <embed> tags:

<object class="sml" data="test1.svg" type="image/svg+xml">
    <embed class="sml" src="test1.svg" type="image/svg+xml" />
</object>