The picture element and associated features are W3C standard HTML features that allow web developers to deliver an appropriate image to every user depending on a variety of conditions like screen size, viewport size, screen resolution, and more. Picturefill is a JavaScript file (or a polyfill to be more specific) that enables support for the picture
element and associated features in browsers that do not yet support them, so you can start using them today!
Picturefill is developed and maintained by , with help from the members of the Responsive Images Community Group and the developer community at large. For Picturefill version 2, a special thanks goes to Shawn Jansepar for all his work on polyfilling the new spec.
For more information on the development of Picturefill, and how you can file bugs or contribute fixes, check out the the code project site on Github : Picturefill on Github.
For native picture
element support, you'll want Picturefill version 2. These downloads include the matchMedia polyfill for browsers that need it (like IE9).
Version 1.2.1 of Picturefill is available if you are interested in the older markup pattern that uses span
elements. This version is a lot lighter in weight than version 2 and allows for a fallback image in browsers that have JavaScript disabled (whereas Picturefill version 2 only offers alt
text as a fallback for non-JS browsers without picture
support).
For basic usage of Picturefill: download one of the files listed above and reference it from the head
section of your HTML document with the following code:
<script src="picturefill.js"></script>
To allow your page to load more efficiently, we'd recommend adding an async
attribute to that script
tag as well. This tells the browser that it can load picturefill asynchronously, without waiting for it to finish before loading the rest of the document. 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 picture
elements if it encounters them in the page before picturefill has finished loading.
Here's our recommended snippet:
<script>
// Picture element HTML5 shiv
document.createElement( "picture" );
</script>
<script src="picturefill.js" async></script>
Note that 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. Also, more advanced users may not need this may choose to load Picturefill dynamically using a script loader like Require.js, (AMD and CommonJS support is included in the script).
Once you've included picturefill.js, you can start adding responsive image elements to your site. Picturefill adds support for both the picture
element and also new responsive attributes to the img
element. You may find that the new img
features may be all you need. Let's cover those first.
img
with srcset
& sizes
attributesThe sizes
syntax is used to define the size of the image across a number of breakpoints. srcset
then defines an array of images and their inherent sizes. It's beyond the scope of this guide to get into much detail about how to use the new srcset
& sizes
attributes, so we'd recommend reading the following post by Eric Portis: Srcset and Sizes. Read that first, then check out the demos below!
<img sizes="(min-width: 40em) 80vw, 100vw"
srcset="examples/images/medium.jpg 375w, examples/images/medium.jpg 480w, examples/images/large.jpg 768w" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
Here's how that renders in the browser. Feel free to resize to see it change.
picture
elementThe picture
element requires a little more markup than the example above, but it allows you to use features like CSS3 Media Queries to pair image sources with other layout conditions in your designs.
Your picture
element should contain a series of source
elements followed by an img
element. Each source
element must have a srcset
attribute specifying one or more image url sources (which can use expanded srcset syntax if desired for resolution switching), and the img
element should have a srcset attribute for fallback purposes as well (some browsers like Android 2.3's won't see the source
elements). Additionally, you may add a media
attribute containing CSS3 Media Queries, and/or a sizes
attribute to pair with srcset
.
Here's one with srcset
and media
. The first source
with a media
attribute that matches the user’s context will determine the src of the img
element at the end, so you’ll want to present larger options first when using min-width
media queries (like in the examples below), and larger options last when using max-width
media queries.
<picture>
<source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
<img srcset="examples/images/medium.jpg" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
</picture>
While most versions of IE (even older ones!) are supported well, IE9 has a little conflict to work around. To support IE9, you will need to wrap a video
element wrapper around the source elements in your picture
tag. You can do this using conditional comments, like so:
<picture>
<!--[if IE 9]><video style="display: none;"><![endif]-->
<source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
<!--[if IE 9]></video><![endif]-->
<img srcset="examples/images/medium.jpg" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
</picture>
Here's how that renders in the browser. Feel free to resize to see it change.
media
and srcset
syntax:The 1x
, 2x
syntax in srcset
acts as a shorthand for more complex resolution media queries. When natively supported, srcset
will allow the UA to override requests for higher-resolution options based on a bandwidth limitations or a user preference (see #9 in the Responsive Images Use Cases and Requirements).
<picture>
<!--[if IE 9]><video style="display: none;"><![endif]-->
<source srcset="examples/images/large.jpg, examples/images/extralarge.jpg 2x" media="(min-width: 800px)">
<source srcset="examples/images/small.jpg, examples/images/medium.jpg 2x">
<!--[if IE 9]></video><![endif]-->
<img srcset="examples/images/small.jpg, examples/images/medium.jpg 2x" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
</picture>
media
example with one webp source qualified with a type
attribute.Note: Picturefill supports SVG and WebP types on any source element, and will disregard a source
if its type is not supported in a particular environment:
<picture>
<!--[if IE 9]><video style="display: none;"><![endif]-->
<source srcset="examples/images/large.webp" media="(min-width: 800px)" type="image/webp">
<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
<source srcset="examples/images/medium.jpg" media="(min-width: 400px)">
<!--[if IE 9]></video><![endif]-->
<img srcset="examples/images/small.jpg" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
</picture>
Under ordinary circumstances, you likely won't need to do more than include picturefill.js in your page, but in some situations you may want to run picturefill's function manually yourself, and there are a few options to keep in mind:
Picturefill.js exposes a single global function: the picturefill()
function. picturefill()
is automatically called one or more times while a page is loading, and it also is triggered when the browser window is resized (or on orientation change). You can run the picturefill()
function at any time in JavaScript yourself as well, which may be useful after making updates to the DOM, or when conditions relevant to your application change:
picturefill();
When running the picturefill()
function, you can pass options specifying the following settings:
picture
and img[srcset]
elements you'd like picturefill to evaluate. The Default value for options.elements
is all picture
and img[srcset]
elements in the page.
picturefill( {
elements: [ document.getElementById( "myPicture" ) ]
} );
options.elements
array, even if they've already been evaluated. The default is false
, except when a resize event triggers Picturefill to run (options.reevaluate
is true
in that case).
picturefill( {
reevaluate: true
} );
Picturefill supports a broad range of browsers and devices, provided that you stick with the standard markup conventions documented above.
Picturefill is tested broadly and works in a large number of browsers. That said, it does have some browser support considerations to keep in mind:
picture
element, non-picture
supporting browsers will only see alt
attribute text as a fallback when JavaScript fails or is disabled. This is because any noscript
-based workarounds (such as the one used in Picturefill version 1) will cause future browsers that support the picture
element to show two images instead of one when JavaScript is off. Unfortunately, choosing to add a src
attribute to the img
element in your picture
element isn't a good workaround either, as any browser that exists today will fetch that src
url even if it is not going to be used (which is wasteful). If you absolutely need an image to appear in non-JS environments, Picturefill 1.2 is a fine choice.srcset
but do not yet support the picture
element, users may experience a wasted HTTP request for each picture
element on a page. This is because the browser's preparser will fetch one of the URLs listed in the picture
element's child img
's srcset
attribute as soon as possible during page load, before the JavaScript can evaluate the potential picture
source
elements for a better match. This problem will only affect browsers that have implemented srcset
but not picture
, which will hopefully be short-lived.source
elements inside a picture
element. For IE, the video
tag workaround helps us avoid this problem, but Android will still have no access to source
elements. Be sure to provide a srcset
attribute on your enclosed img
to ensure an image will show in this browser.picture
element (paired with picturefill) works best in browsers that support CSS3 media queries. Picturefill includes the matchMedia polyfill by default, which makes matchMedia work in media query-supporting browsers that don’t support matchMedia
.