2

I would like to create resolution independent SVG that uses <image> element. Is it possible to test for actual pixel ratio of the user agent? Please look at the example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="480">
    <defs>
        <pattern id="test" patternUnits="userSpaceOnUse"
            x="0" y="0" width="130" height="100"
            viewBox="0 0 130 100" >
            <IF PIXEL RATIO = 2>
                <image xlink:href="test_2x.png" id="svg_1" height="100" width="130" y="0" x="0"/>
            <ELSE>
                <image xlink:href="test.png" id="svg_1" height="100" width="130" y="0" x="0"/>
            <END IF>
        </pattern> 
    </defs>
    <rect id="rectangle" stroke="rgb(29, 29, 255)"  fill="url(#test)" x="50" y="47" width="320" height="240" />
</svg>

I only have found Switch Element in the documentation but it doesn't seem to be very helpful since there is no "retina display" feature. Or is there? :)

mato
  • 173
  • 8

1 Answers1

3

You could use CSS media selectors to detect retina displays. Using the display property, you can switch the images on and off depending on the device.

I don't have an Apple retina device at hand to test, but I think something like this should work:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="480">
  <style type="text/css">
    @media all {
      #test_2x_png {display:none}
    }
    @media (-webkit-min-device-pixel-ratio: 2) {
      #test_png    {display:none;}
      #test_2x_png {display:inline;}
    }
  </style>
  <defs>
    <pattern id="test" patternUnits="userSpaceOnUse"
        x="0" y="0" width="130" height="100"
        viewBox="0 0 130 100" >
          <image xlink:href="test_2x.png" height="100" width="130" y="0" x="0" id="test_2x_png"/>
          <image xlink:href="test.png" height="100" width="130" y="0" x="0" id="test_png"/>
    </pattern> 
  </defs>
  <rect id="rectangle" stroke="rgb(29, 29, 255)"  fill="url(#test)" x="50" y="47" width="320" height="240" />
</svg>
Thomas W
  • 14,757
  • 6
  • 48
  • 67
  • Ah that's clever. I gave up on media queries as they don't allow to change the xlink reference, but that's a pretty nifty solution. – methodofaction Dec 27 '12 at 16:13
  • this is great, thanks! Only tiny thing is that `@media all` must be first, but other than that your solution is perfect. – mato Dec 28 '12 at 07:43
  • Thanks, I'll fix this in my answer so that others can better make use of it. – Thomas W Dec 28 '12 at 10:08
  • 2
    This technique held promise, but it doesn't work correctly for the typical high dpi use case. If you look at the network inspector, you see that both images are downloaded whether you are on a retina screen or not. Setting the display of the image element (or its parent) to none does not prevent the download of the image as it does with css background images, it only switches the displayed image. Since you're loading both anyway, there's no reason not to just use the retina resolution if it's just a matter of quality. – Dwight Aug 18 '15 at 19:49
  • @Dwight That's of course a very valid point. JavaScript would help, but for SVGs used by HTML `` elements, this won't work AFAIK. – Thomas W Aug 19 '15 at 05:24
  • @ThomasW I've been researching it extensively for days. I have found no technique that can suppress the automatic loading of xhref:link urls. If you can represent your SVG as a masked layer on top of a single background image, you can achieve some very limited positive results with the Clown Car technique. – Dwight Aug 20 '15 at 16:51
  • For the record - a [link to the Clown Car Technique article](http://www.smashingmagazine.com/2013/06/clown-car-technique-solving-for-adaptive-images-in-responsive-web-design/). You might also consider making your SVG inline and use JavaScript DOM manipulation to add the most appropriate raster image. – Thomas W Aug 21 '15 at 05:54