Better SVG Fallback and Art Direction With The picture Element
Articles & Blogs

Better SVG Fallback and Art Direction With The picture Element

Feb 14, 2015

<p class="deck">Besides using an SVG as a background image in CSS, you can serve SVG foreground images in HTML using one of several embedding techniques, each of which has its advantages and use cases. Unless you’re in need of interactivity or external styling, <code><img /></code> is the standard way for loading an SVG image, but it has one disadvantage: you currently need JavaScript to provide fallback and/or change the image source for art direction. In this post, I’ll talk about a better way to do that, using the <code><picture></picture></code> element.</p> <p>This is not a primer to using <code>&lt;picture&gt;</code>. There are a lot of great resources in the wild that contain everything you need to know about the <code>&lt;picture&gt;</code> element, so if you’re not familiar with it, refer to the last section of the article for a list of resources to learn all about it. That being said, the article does not require any special or strong <code>&lt;picture&gt;</code> skills, as the examples are mostly self-explanatory as you will see.</p> <p class="note"> This article is also <a href="http://css-live.ru/articles/obespechenie-luchshej-rezervnoj-podderzhki-svg-i-upravlenie-oformleniem-s-pomoshhyu-elementa-picture.html">available in Russian</a>. </p> <h3 class="deeplink" id="the-current-img">The Current <code><img /></code></h3> <p>Before getting into why <code>&lt;picture&gt;</code> is a great option for SVG, let’s lay down (an overview of) the limitations and disadvantages of using <code>&lt;img&gt;</code> for responsive SVG work.</p> <p>Normally, if you load an SVG using an <code>&lt;img&gt;</code> tag, you can provide fallback and change the source of the image on different viewport sizes using feature detection and media queries in JavaScript. My choice for both would be to use <a href="http://modernizr.com/">Modernizr</a> for both; that is, unless you’re only serving one image, in which case adding Modernizr might be overwork, and something like this:</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo.svg<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">onerror</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token keyword">this</span><span class="token punctuation">.</span>src<span class="token operator">=</span>logo<span class="token operator">-</span>fallback<span class="token punctuation">.</span>png<span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>onerror<span class="token operator">=</span><span class="token keyword">null</span><span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span> <span class="token punctuation">/></span></span></span></code></pre> <p>…would be simpler and faster.</p> <p>Using Modernizr, you can detect browser support for SVG, and provide an alternative image <code>src</code> for when SVG is not supported. The alternative image URL can be stored in a custom data attribute. This approach is particularly useful for when you have multiple images on the page whose <code>src</code> you need to switch.</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo.svg<span class="token punctuation">"</span></span> <span class="token attr-name">data-fallback</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo.png<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span></code></pre> <p>Using Modernizr, you can detect whether or not the browser supports SVG and then take necessary steps to provide the fallback based on the test result:</p> <pre class="language-js"><code class="language-js"><span class="highlight-line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Modernizr<span class="token punctuation">.</span>svg<span class="token punctuation">)</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token comment">// fetch fallback and replace img src with it</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre> <p>You can also use Modernizr’s media query detection to change the img src on based on viewport width for when you want to do art direction and not load the same big SVG on smaller screens:</p> <pre class="language-js"><code class="language-js"><span class="highlight-line"><span class="token keyword">if</span> <span class="token punctuation">(</span>Modernizr<span class="token punctuation">.</span><span class="token function">mq</span><span class="token punctuation">(</span><span class="token string">'(max-width: 640px)'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token comment">// replace image source with the smaller SVG source</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre> <p>You don’t need to store any URLs in data attributes in this case if you are following a specific naming convention for your images. For example, if your images are named <code>view-small.svg</code>, <code>view-big.svg</code>, you can just replace the <code>view-*</code> part with the appropriate one in the JavaScript and be done with it.</p> <p>Now, if you want to provide a PNG or JPEG fallback for your SVG <em>and</em> also provide different sizes of that fallback image to match the viewport size, Modernizr will also do, but it will get slightly more complicated. And the most important part is: you need JavaScript to do it.</p> <p>With the <code>&lt;picture&gt;</code> element, we can do all that and more, without JavaScript. Well, kind of. Read on.</p> <h3 class="deeplink" id="the-bigger-picture">The Bigger <code><picture></picture></code></h3> <p>The <code>&lt;picture&gt;</code> element provides us with a better JavaScript-less way to change the image we are serving based on different media queries <em>and</em> a for providing fallback for non-supporting browsers (or browsers that can’t load the SVG for any reason).</p> <h4 class="deeplink" id="loading-and-providing-fallback">Loading An SVG and Providing Fallback For Non-Supporting Browsers</h4> <p>Let’s start with fallback first. Providing fallback for browsers that can’t load the SVG is as simple as wrapping your <code>&lt;img&gt;</code> fallback in a <code>&lt;picture&gt;</code> element, and referencing your SVG in a <code>&lt;source&gt;</code> element:</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>picture</span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>path/to/image.svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>path/to/fallback.png<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Image description<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>picture</span><span class="token punctuation">></span></span></span></code></pre> <p>The <code>&lt;picture&gt;</code> element is just a wrapper for the elements used to load the image(s) you want and for the fallback provided with the <code>&lt;img&gt;</code> element. The <code>&lt;img&gt;</code> element is <em>required</em> for <code>&lt;picture&gt;</code> to work and is used to provide backwards compatibility for browsers that don’t support <code>&lt;picture&gt;</code> or, like our case here, browsers that can’t load or don’t support the the image(s) [type] you load in the <code>&lt;source&gt;</code> element.</p> <p>The <code>&lt;source&gt;</code> element is where we specify the image(s) we want. We’re specifying the type of the image we want (SVG) in the <code>type</code> attribute, and providing the URL to that image in the <code>srcset</code> attribute. And that’s all there really is to it; this is how simple it is to provide fallback for an SVG image using <code>&lt;picture&gt;</code>—no JavaScript is needed.</p> <p>You can take this even further and provide multiple fallback images that take screen resolution into account; to do that you can specify those images using the <code>srcset</code> attribute on the <code>&lt;img&gt;</code>. For example:</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>picture</span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>path/to/logo.svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>path/to/logo-1x.png<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>path/to/logo-2x.png 2x, path/to/logo-3x.png 3x<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Logo description<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>picture</span><span class="token punctuation">></span></span></span></code></pre> <p>The browser can then choose the image it finds appropriate based on the screen resolution. This is useful for when you are serving the same image size (for example, a one-size logo) but want to provide 2x and 3x versions for higher resolutions.</p> <p>But if you want you can take it even <em>further</em>. With the help of the <code>sizes</code> attribute, you can use media queries on the <code>&lt;img&gt;</code> to change the fallback image size on different screen sizes, providing a bigger image for bigger screens and a smaller one for small screens.</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>picture</span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>path/to/banner.svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span><br /><span class="highlight-line"> <span class="token attr-name">sizes</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(min-width: 640px) 80vw, 100vw<span class="token punctuation">"</span></span></span><br /> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>banner-300.jpg 300w,<br /><span class="highlight-line"> banner-400.jpg 400w,</span><br /><span class="highlight-line"> banner-700.jpg 700w,</span><br /><span class="highlight-line"> banner-1200.jpg 1200w,</span><br /><span class="highlight-line"> banner-1600.jpg 1600w,</span><br /> banner-2000.jpg 2000w<span class="token punctuation">"</span></span><br /><span class="highlight-line"> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>banner-default-fallback.jpg<span class="token punctuation">"</span></span></span><br /> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Banner description<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>picture</span><span class="token punctuation">></span></span></span></code></pre> <p>What we’ve done here is we told the browser in the <code>sizes</code> attribute what size our image will occupy on the page. In this case, if the width of the viewport is 640px or more, the image will be 80% the width of the viewport, and 100% the width otherwise.</p> <p>Then, in the <code>srcset</code> attribute, we provided the browser with a list of images—they are all the same image, but in different sizes. Based on the sizes specified in <code>sizes</code>, the browser will pick the best fit among these images and display it.</p> <p>If a browser does not support <code>srcset</code> on <code>&lt;img&gt;</code>, it will simply display the fallback specified in the <code>src</code> attribute. For a detailed explanation of how this works, refer to <a href="http://alistapart.com/article/responsive-images-in-practice">this article</a> over at A List Apart.</p> <h4 class="deeplink" id="art-direction">Art Direction: Loading a Different SVG on Different Screen Sizes</h4> <p>The <code>&lt;source&gt;</code> element we use to specify the image(s) we want comes with another attribute: <code>media</code>. This attribute provides us with the same flexibility we have for changing background images in CSS using CSS media queries, by allowing us to pair image sources with layout conditions (the media queries) right in the source code.</p> <p>Since we’re serving an SVG image, we don’t need to serve multiple versions of the image for different screen resolutions because of the infinitely scalable nature of SVG which makes it look great on any resolution. (Yay!)</p> <p>But if we have an SVG that we’re serving on desktop—for example, a wide header image, this image could be hundreds of kilobytes in size. Serving the same big image for small screens might not be the best idea if you look at it from a performance angle. Moreover, maybe you just <em>don’t want</em> to serve the same image on smaller sizes, but a “cropped” version of that image. I recently worked on a client project that required just that. Not only did my client want different images on smaller sizes, but the full composition was more than 100KB in size, which is obviously too much to serve on mobile devices, so we served cropped versions of that image.</p> <p>In such a case, you can specify different SVGs to load on different media conditions using the <code>media</code> attribute on the <code>&lt;source&gt;</code>. In the <code>media</code> attribute, you specify the media conditions similar to how you do it in CSS media queries.</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>picture</span><span class="token punctuation">></span></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span><br /><span class="highlight-line"> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(max-width: 640px)<span class="token punctuation">"</span></span></span><br /><span class="highlight-line"> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>header--small.svg<span class="token punctuation">"</span></span></span><br /> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span><br /><span class="highlight-line"> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(max-width: 1024px)<span class="token punctuation">"</span></span></span><br /><span class="highlight-line"> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>header--medium.svg<span class="token punctuation">"</span></span></span><br /> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span><br /><span class="highlight-line"> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>header--full.svg<span class="token punctuation">"</span></span></span><br /> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>header--default-fallback.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Header description..<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>picture</span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"></span></code></pre> <p>Of course, you can specify different fallback images for different resolutions and sizes, similar to what we did in the previous section. For the sake of brevity, I’m going to skip that step in this section, but you get the picture. (See what I did there?)</p> <p>You can also specify multiple sizes of each SVG image and let the browser pick the one it finds best, like we did for the fallback image before. However, due to the scalable nature of SVG, this might not be necessary.</p> <p>As a matter of fact, the options the <code>&lt;picture&gt;</code> element comes with cover practically any scenario. <a href="https://dev.opera.com/articles/responsive-images/">This article</a> on the dev.opera blog covers a lot of these use cases with practical examples and snippets to help you get started.</p> <hr /> <p>So, you see, with the <code>&lt;picture&gt;</code> element, we no longer need to use JavaScript to provide fallback and/or change the image based on different media conditions. Well, kind of…</p> <h3 class="deeplink" id="browser-support-and-polyfilling">Browser Support and Polyfilling</h3> <p>At the time of writing of this article, browser support for <code>&lt;picture&gt;</code> isn’t at its best, but it is getting better. A lot of smart people are working on <code>&lt;picture&gt;</code> implementation across browsers. Keep an eye on <a href="http://caniuse.com/#feat=picture">the compatibility table over at CanIUse.com</a> to stay up-to-date on browser support in the future.</p> <p>In the meantime, and until browser support becomes more decent, you can use a JavaScript polyfill for non-supporting browsers. So yes, we do need JavaScript at the moment, but the code you write will be future-proof and all you need to do in the future when support gets better is to remove the polyfill, and your code will work without it as expected. Using <code>&lt;img&gt;</code> you’d need to do much more, or, at least, just keep using Javacript.</p> <p>The <a href="http://scottjehl.github.io/picturefill/">Picturefill</a> polyfill by the folks at the Filament Group is the current de facto for cross-browser <code>&lt;picture&gt;</code> support today. The polyfill homepage contains extensive documentation on how to use the polyfill and tips on using <code>&lt;picture&gt;</code> in general along with general patterns.</p> <p>Using the polyfill is as simple as including the script in your page’s <code>head</code>:</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>picturefill.js<span class="token punctuation">"</span></span> <span class="token attr-name">async</span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></span></code></pre> <p>The <code>async</code> attribute tells the browser that it can load picturefill asynchronously, without waiting for it to finish before loading the rest of the document. According to the Picturefill documentation, If you add this attribute, you’ll need to add a line of script before the script tag as well to allow older browsers to recognize <code>picture</code> elements if it encounters them in the page before Picturefill has finished loading.</p> <pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /><span class="highlight-line"> <span class="token comment">// Picture element HTML5 shiv</span></span><br /><span class="highlight-line"> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span> <span class="token string">"picture"</span> <span class="token punctuation">)</span><span class="token punctuation">;</span></span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>picturefill.js<span class="token punctuation">"</span></span> <span class="token attr-name">async</span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></span></code></pre> <p>If you are <a href="http://www.paulirish.com/2011/the-history-of-the-html5-shiv/">familiar with HTML5 Shiv</a>, then you already know what this line is needed for. As a matter of fact, if you are already including a recent version of the HTML5 Shiv (sometimes packaged with Modernizr), you may not need this line as it is included there as well.</p> <h4 class="deeplink" id="fixing-ie9">Fixing IE9</h4> <blockquote> <p>While most versions of IE (even older ones!) are supported [by Picturefill] well, IE9 has a little conflict to work around. To support IE9, you will need to wrap a <code>video</code> element wrapper around the <code>source</code> elements in your <code>picture</code> tag. You can do this using conditional comments. — <a href="http://scottjehl.github.io/picturefill/">Picturefill homepage</a></p> </blockquote> <p>As the documentation says, the polyfill provides support for <code>&lt;picture&gt;</code> across browsers, but IE9 requires that you wrap your <code>source</code> elements in a <code>video</code> tag. And since this fix is only required for IE9, you can place it in IE9-targeting conditional comments:</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>picture</span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"><span class="token comment">&lt;!--[if IE 9]>&lt;video style="display: none;">&lt;![endif]--></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token punctuation">></span></span></span><br /><span class="highlight-line"><span class="token comment">&lt;!--[if IE 9]>&lt;/video>&lt;![endif]--></span></span><br /><span class="highlight-line"> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>..<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>picture</span><span class="token punctuation">></span></span></span></code></pre> <h3 class="deeplink" id="foreground-svg-images">Foreground SVG Images with Interactivity and Styleability</h3> <p>As mentioned at the beginning of the article, the <code>&lt;img&gt;</code> element, and naturally the <code>&lt;picture&gt;</code> element, only allow you to load a static SVG image, or an SVG with animations defined internally. If you need to load a foreground image and you want that image to be interactive and styleable, you can use one of four available ways: <code>&lt;object&gt;</code>, <code>&lt;iframe&gt;</code>, <code>&lt;embed&gt;</code> and inline <code>&lt;svg&gt;</code>.</p> <p>Both the <code>&lt;iframe&gt;</code> and <code>&lt;object&gt;</code> come with a default fallback mechanism.</p> <pre class="language-html"><code class="language-html"><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>object</span> <span class="token attr-name">data</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image.svg<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image/svg+xml<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token comment">&lt;!-- fallback here --></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>object</span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>iframe</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>image.svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></span><br /><span class="highlight-line"> <span class="token comment">&lt;!-- fallback here --></span></span><br /><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>iframe</span><span class="token punctuation">></span></span></span></code></pre> <p>An inline <code>&lt;svg&gt;</code> requires a different approach to provide fallbacks; one such approach uses the <code>&lt;foreignObject&gt;</code> element. You can read all about it <a href="http://www.kaizou.org/2009/03/inline-svg-fallback/">here</a>. Chris has also written about providing fallback for SVG <a href="http://css-tricks.com/svg-fallbacks/#the-fallbacks">here</a>.</p> <h3 class="deeplink" id="final-words">Final Words</h3> <p>While using <code>&lt;picture&gt;</code> currently does require adding a JavaScript polyfill, using standard HTML5 markup and getting the flexibility of switching images using native elements is extremely powerful, and plugging the polyfill in is as easy as 1. download it, 2. add script to page, 3. you’re done. It’s absolutely worth it if you are doing art direction or providing fallback for multiple foreground SVG images.</p> <p><code>&lt;picture&gt;</code> is more likely to become the standard way for art-directing SVG and providing <code>img</code> fallback in the future, so why start using it today? Both <code>img</code> way and the new <code>picture</code> require some JavaScript—for now, but the latter is definitely cleaner and more future-proof. Yes, <code>img</code> is also future-proof, but at some point, you get to ditch the polyfill and keep your code unchanged if you use <code>picture</code>, while <code>img</code> will either require you to keep using JavaScript <em>or</em> refactor your markup to make the switch to JavaScript-less <code>picture</code>.</p> <p>Whether you decide to start using <code>&lt;picture&gt;</code> for SVG today or not, it is definitely worth getting to know better and using it for serving other responsive image formats. So here is a list of recommended articles to get you up and running:</p> <h3 id="recommended-reading-on-%3Cpicture%3E" tabindex="-1">Recommended Reading on <code>&lt;picture&gt;</code></h3> <ul> <li><a href="http://www.html5rocks.com/en/tutorials/responsive/picture-element/">Introducing the <code>&lt;picture&gt;</code> element</a></li> <li><a href="https://dev.opera.com/articles/native-responsive-images/">Native Responsive Images</a></li> <li><a href="http://alistapart.com/article/responsive-images-in-practice">Responsive Images in Practice</a></li> <li><a href="https://dev.opera.com/articles/responsive-images/">Responsive Images: Use Cases and Documented Code Snippets to Get You Started</a></li> <li><a href="http://demosthenes.info/blog/936/Responsive-Images-For-Designers-The-HTML5-picture-element">Responsive Images For Designers: The HTML5 picture element</a></li> </ul>

Jump to
Projectsbrowse
Peoplebrowse
Companiesbrowse
Saved
Editor
Autosaves as you type