Note: Better docs and demos are coming soon
I know what you're thinking. Aren't there enough responsive image solutions by now? Until <picture>
is standard and we can use it everywhere, I'm going to say "no".
I like to think that it's a best-of-all-worlds solution, which addresses the requirements that Mat Marquis lists in his article So, You're Writing A Responsive Images Script:
- Only makes 1 request for the image's current situation.
- Easily allows a
<noscript>
fallback for users without JavaScript. If JavaScript breaks then so does the script, but that goes for all non-native solutions. - It supports "art direction", ie. the ability to load "sources that make use of different cropping, zooming, and focal points".
- It actually works in the real-world. I've been using early prototypes of the plugin internally at XO Digital, and have just included this in our latest soon-to-be-released project for a well-recognised brand.
In addition to the above, rwd.images.js:
- Uses a familar CSS/media query syntax for determining the appropriate image src.
- Can automatically convert pixel-based media queries to ems.
- Supports high-DPI/retina versions when a consistent naming convention is used.
- Supports fallback images for browsers that don't support media queries.
- Supports lazy-loading of images.
- Is not restricted to just
<img>
tags. It can be applied to any element (<div>
s etc) for use as backgrounds. - Works using either a mobile-first or a desktop-down philosophy.
- Has no dependencies, but when combined with enquire.js, is even easier to use and allows users to download and share images as expected.
- Is only ~1.7 KB minified and gzipped.
rwd.images.js uses the .rwdimage
class, a series of [data-rwdimage]
attributes and "CSS" to set up a responsive image.
Since the plugin solves the responsive image problem with a background-image
"workaround", by loading @WickyNilliams' enquire.js before rwd.images.js, the <img src>
will also be set to the correct filename so users can share or download it.
<img class="rwdimage" data-rwdimage="
{ src: url(/images/4-by-3.jpg); },
(min-width: 501px) { src: url(/images/16-by-9.jpg); }
" />
<!-- Also load the matchMedia polyfills -->
<script src="/js/enquire.min.js"></script>
<script src="/js/rwd.images.min.js"></script>
</body>
At its simplest, that's it!
.rwdimage
instructs the script that this image needs to be "made responsive".[data-rwdimage]
is passed a comma-separated list of CSS-like rules without a selector:src
is the path to the image that should be set for that breakpoint (or by default if no media query is used)
So, the <img>
:
- Will display
4-by-3.jpg
by default; and - At 501px, will be switched to display
16-by-9.jpg
.
Note that media queries in JavaScript do not behave identically to those in CSS. If you don't specify a max-width
media query for the breakpoints, the image's src
will not be replaced when resizing the browser from wide to narrow.
<img class="rwdimage" data-rwdimage="
{ src: url(/images/4-by-3.jpg); padding-bottom: ratio(3/4); },
(min-width: 501px) { src: url(/images/16-by-9.jpg); padding-bottom: ratio(9/16); }
" />
<script src="/js/rwd.images.min.js"></script>
</body>
The only difference here is the padding-bottom: ratio(y,x)
property. The parameters get evaluated and converted in to an intrinsic percentage ratio. You can pass in the actual dimensions of the image, or break it down to its smallest fraction like I have here.
Now let's use some more of the options available in rwd.images.js:
<img class="rwdimage" data-rwdimage="
{ src: url(/images/4-by-3.jpg); },
(min-width: 501px) { src: url(/images/16-by-9.jpg); }
" data-rwdimage-fallback="
{ src: url(/images/16-by-9.jpg); }
" data-rwdimage-em="true" data-rwdimage-retina="true" />
The <img>
:
- Will display
4-by-3.jpg
by default- But
[email protected]
for high-DPI/retina devices
- But
- At 31.3125em (501 ÷ 16) will display
16-by-9.jpg
- But
[email protected]
for high-DPI devices
- But
- Will also display
16-by-9.jpg
for the oldIE fallback (.ltie9
)
So here we can see how em-based media queries, retina images and old IE can easily be supported using rwd.images.js with minimal effort.
Using the remaining [data-rwdimage-*]
attributes, we can achieve even more:
[data-rwdimage-em-base]
: To change the base font size for the calculation of media queries from 16px. Some developers like to sethtml { font-size: 62.5%; }
so set-em-base
to 10.[data-rwdimage-fallback-class]
: The class onhtml
used to target the fallback browser. The default isltie9
, but you may like to set it tolt-ie9
orno-mq
if using Modernizr to detect media query support.[data-rwdimage-retina-suffix]
: The suffix used for high-DPI/retina image filenames. The default is@2x
. Filenames must follow the convention: [filename][suffix][extension].[data-rwdimage-lazy-load]
: Set totrue
to only load the<img>
's relevant src when it has a class oflazy-loaded
applied.
Note: If using enquire.js and [data-rwdimage-lazy-load="true"]
to lazy-load images, you must also call window.rwdImageChangeSrc(img)
when applying the .lazy-loaded
class.
Something like:
<script src="/js/enquire.min.js"></script>
<script src="/js/rwd.images.min.js"></script>
<script>
(function() {
// Get all images
var $images = document.getElementsByClassName('rwdimage');
var lazyLoad = function($image) {
$image.className += ' lazy-loaded';
window.rwdImageChangeSrc($image);
};
// Lazy-load them all (don't use this in production!)
for (var i = 0; i < $images.length; i++) {
lazyLoad($images[i]);
}
})();
</script>
If not using enquire.js, there may be times where your image is outside of a container that constrains its size. This will lead to the image continuing to scale past its original, and intended maximum size.
To prevent this, set a relevant breakpoint to reset the image's dimensions, and also apply it to the fallback if appropriate:
<img class="rwdimage" data-rwdimage="
{ src: url(/images/4-by-3.jpg); padding-bottom: ratio(3/4); },
(min-width: 501px) { src: url(/images/16-by-9.jpg); padding-bottom: ratio(9/16); }
(min-width: 1000px) { height: 562px; padding-bottom: 0; width: auto; }
" data-rwdimage-fallback="
{ src: url(/images/16-by-9.jpg); height: 562px; padding-bottom: 0; width: auto; }
" />
Copyright (c) 2014 Matt Stow
Licensed under the MIT license (see LICENSE for details)
Minified version created with Online YUI Compressor: http://www.refresh-sf.com/yui/