2022 Update:

A lot has changed on the web since this post was written. The described effect can now be achieved with pure css using object-fit. Unless you’re targeting legacy browsers, use object-fit: cover. Browser support for object-fit can be found here.

Original post:

Recently I came across a problem whereby I had to dynamically resize an image to fill its parent container, exactly like the background-size: cover CSS property but using an image tag instead. The requirements are pretty straightforward – upscale if the image is too small, downscale if it’s too large, and always resize based on the smallest dimension in relation to the aspect ratio of the parent container (which means that you’ll never see any whitespace, the image will always overflow on either height or width). Strangely enough I couldn’t find a jQuery plugin to do quite what I wanted, so I created one.

Check out the demo to see it in action.

The plugin is as follows (also available on github):

/*
* Plugin Name: Resize Image to Parent Container
*
* Author: Christian Varga
* Author URI: http://christianvarga.com
* Plugin Source: https://github.com/levymetal/jquery-resize-image-to-parent/
*
*/
(function($) {
$.fn.resizeToParent = function(opts) {
var defaults = {
parent: 'div',
delay: 100
}
var opts = $.extend(defaults, opts);
function positionImage(obj) {
// reset image (in case we're calling this a second time, for example on resize)
obj.css({'width': '', 'height': '', 'margin-left': '', 'margin-top': ''});
// dimensions of the parent
var parentWidth = obj.parents(opts.parent).width();
var parentHeight = obj.parents(opts.parent).height();
// dimensions of the image
var imageWidth = obj.width();
var imageHeight = obj.height();
// step 1 - calculate the percentage difference between image width and container width
var diff = imageWidth / parentWidth;
// step 2 - if height divided by difference is smaller than container height, resize by height. otherwise resize by width
if ((imageHeight / diff) < parentHeight) {
obj.css({'width': 'auto', 'height': parentHeight});
// set image variables to new dimensions
imageWidth = imageWidth / (imageHeight / parentHeight);
imageHeight = parentHeight;
}
else {
obj.css({'height': 'auto', 'width': parentWidth});
// set image variables to new dimensions
imageWidth = parentWidth;
imageHeight = imageHeight / diff;
}
// step 3 - center image in container
var leftOffset = (imageWidth - parentWidth) / -2;
var topOffset = (imageHeight - parentHeight) / -2;
obj.css({'margin-left': leftOffset, 'margin-top': topOffset});
}
// run the position function on window resize (to make it responsive)
var tid;
var elems = this;
$(window).on('resize', function() {
clearTimeout(tid);
tid = setTimeout(function() {
elems.each(function() {
positionImage($(this));
});
}, opts.delay);
});
return this.each(function() {
var obj = $(this);
// hack to force ie to run the load function... ridiculous bug
// http://stackoverflow.com/questions/7137737/ie9-problems-with-jquery-load-event-not-firing
obj.attr("src", obj.attr("src"));
// bind to load of image
obj.on('load', function() {
positionImage(obj);
});
// run the position function if the image is cached
if (this.complete) {
positionImage(obj);
}
});
}
})( jQuery );

To use it, ensure that the image is positioned relatively or absolutely inside a wrapper element which has the `overflow: hidden` property set (so the image can take up the entire height/width of the wrapper with the cropped portion hidden). Then, simply call resizeToParent on your image like so (remembering to put it inside the jQuery ready function):

$('#myImage').resizeToParent();
view raw direct.js hosted with ❤ by GitHub

The plugin will automatically resize the image as soon as it’s finished loading. By default, the image will get resized to the nearest parent div. If you want to target a specific parent, simply pass a selector to the function as the ‘parent’ parameter, like so:

$('#myImage').resizeToParent({parent: '.parentContainer'});
view raw with-parent.js hosted with ❤ by GitHub

Don’t forget that the parent container must have `overflow: hidden` so that the image doesn’t spill out of the parent, and the image must be positioned relatively or absolutely for it to be centered correctly. If you have any doubts, check the source of the demo to see how it works.

Please feel free to leave any questions, comments, or suggestions in the comments below 🙂

If this post has helped you out, feel free to consider throwing a small donation my way.