How to Resize Image Proportionally using JavaScript

We’re continuing a series of “How-to’s” for JavaScript beginners. In this tutorial we will explain how to proportionally resize images. Most tutorials that we have written utilize JavaScript platforms other than MooTools, so we decided to create this one using Mootools, however the function which will resize image’s size can be used with any framework (i.e. jQuery, ExtJS, script.aculo.us or just plain JavaScript.)
We will just use an <img /> tag to resize the images. The actual task of resizing an image proportionally is quite simple, but the most important thing is to calculate the size properly. At first, you should define the size of the bounding box (the maximum size of your image). Let’s say it will be 200×200 pixels:

And we have a photo with a size larger than the bounding box (size 500×313 pixels):

After the image resize we should get something like this:

So that the width of the image will be 200 pixels and height will proportionally scale and become 125 pixels. The image will look smaller, but it keeps its proportions and will still look good.
Now let’s discuss how we will be implementing this in the code. Since we may want to reuse the code at some point in the future, it is best to create a function. First, it is smart to think of all the ways it could be used, how it will work, how you will call the function and also to determine input and output values. A little thought at this time will make the coding task simpler and ensure a more flexible product.
Input parameters of the function will be: maxW, maxH (these parameters will set the size of the bounding box) and currW, currH (these parameters will contain current or original size of the image. In our sample it’s 500×313 pixels). The function will calculate size and return an array containing two values. Usage of the function will be:
{code type=php}
var newSize = scaleSize(200, 200, 500, 313);
alert(’New Width: ‘ + newSize[0] + ‘, New Height: ‘ + newSize[1]);
{/code}
Now let’s implement the algorithm of the scaleSize function. The logic is simple. You just determine the widest side (for landscape photos it will be width and for portrait photos it will be height), then set the size of bounding box to it and calculate the size of the opposite side using the following formula:
For width: currH / currH / currW;
For height: currW * currH / currW;
You will notice that currH / currW expression repeats in both calculations. This is a ratio of height to width. So, here is the actual implementation of the function:
{code type=php}
function scaleSize(maxW, maxH, currW, currH){
var ratio = currH / currW;
if(currW >= maxW && ratio <= 1){
currW = maxW;
currH = currW * ratio;
} else if(currH >= maxH){
currH = maxH;
currW = currH / ratio;
}
return [currW, currH];
}
{/code}
That’s it ;) Click the Demo button to view the code in action.





jared
November 10, 2009
this is a good article i been looking for one like it, but will it work with my jQuery code?
ajaxBlender.com
November 10, 2009
Sure, as mentioned in the tutorial it can be used with any framework since it’s just a plain JavaScript function. We just chose to use the MooTools for the demo script.
karev
December 21, 2009
it is possible to make this script resize all the tag in html page automatically ???
Darren – ajaxBlender
December 22, 2009
Yes, sure here is a quick code. It will adjust size of all images with class “resize-me” to a bounding box of 120×120 pixels:
window.addEvent(’domready’, function(){
$each($$(’IMG.resize-me’), function(imgObj){
var newSize = scaleSize(120, 120, imgObj.width, imgObj.height);
imgObj.width = newSize[0];
imgObj.height = newSize[1];
});
});
Don’t forget to include the code for the ’scaleSize()’ function mentioned in the tutorial.
Karen
February 22, 2010
I feel like an idiot. I am trying to implement the above so that I can use the .resize-me class. I added the class to my image and included the following in the header:
window.addEvent(’domready’, function(){
$each($$(’IMG.resize-me’), function(imgObj){
var newSize = scaleSize(120, 120, imgObj.width, imgObj.height);
imgObj.width = newSize[0];
imgObj.height = newSize[1];
});
});
function scaleSize(maxW, maxH, currW, currH){
var ratio = currH / currW;
if(currW >= maxW){
currW = maxW;
currH = currW * ratio;
} else if(currH >= maxH){
currH = maxH;
currW = currH / ratio;
}
return [currW, currH];
}
Am I missing something?
Darren – ajaxBlender
February 22, 2010
Karen, can you please provide a URL to the above code? We will review and troubleshoot, to provide a fix. Thanks!
gene
April 5, 2010
this code does not seem to work with portrate images
e.g. scaleSize(80,80,225,300) will result in [120,160]
gene
April 5, 2010
should be:
scaleSize(120,120,225,300) will result in [120,160]
sorry for the typo.
gene
April 5, 2010
function scaleSize(maxW, maxH, currW, currH){
var img_ratio = currH / currW;
var box_ratio = maxH /maxW;
if(img_ratio = maxW){
currW = maxW;
currH = currW * img_ratio;
} else if(currH >= maxH){
currH = maxH;
currW = currH / img_ratio;
}
}
else
{
if(currH >= maxH){
currH = maxH;
currW = currH / img_ratio;
} else if(currW >= maxW){
currW = maxW;
currH = currW * img_ratio;
}
}
return [currW, currH];
}
ajaxBlender.com
April 6, 2010
Yes, you are right. Thank you for your comment, however this can be solved much easier:
The condition in ’scaleSize’ function:
if(currW >= maxW){
should be just changed to:
if(currW >= maxW && ratio <= 1){
Thanks,
Alex
gene
April 6, 2010
actually there are other corner cases that this logic does not account for.
for example if container box is 100×400, and image is 400×500 then your function will return 320×400.
i found that it’s needed to compare aspect ratio of the image to the aspect ratio of the container box to properly decide which side to constrain by.
something like
function scaleSize(maxW, maxH, currW, currH){
var img_ratio = currH / currW;
var box_ratio = maxH /maxW;
if(img_ratio
ajaxBlender.com
April 7, 2010
Gene,
Yes you’re right, but there is a shorter, more optimized method for ratio calculation and will work for all cases: ratio = Math.Min(maxW / currW, maxH / currH);
Let us know if any other issues.
Thanks,
Alex
Jeff
July 1, 2010
Hi, I’m trying to convert this to use jQuery but am not having any luck. Can someone tell me what’s missing?
$(document).ready(function() {
var img = $(’image-landscape’);
var initW = img.width, initH = img.height;
$(’.controls LI A’).each(function(el, i){
$(el).click(function(e){
e = new Event(e).stop();
var newW = img.width, newH = 0;
switch(el.rel){
case ‘zoomOut’:
newW -= 20;
break;
case ‘zoomIn’:
newW += 20;
break;
case ‘resizeProportionally’:
var newSize = scaleSize(200, 200, $(el.rev).width, $(el.rev).height);
$(el.rev).width = newSize[0];
$(el.rev).height = newSize[1];
return;
default:
newW = initW;
}
var ratio = initH / initW;
newH = newW * ratio;
img.width = newW;
img.height = newH;
});
});
});
ajaxBlender.com
July 7, 2010
Jeff,
Thanks for your comment. I see several issues with the code.
First, you should change $(’image-landscape’) to $(’.image-landscape’) so that jQuery will search for a proper IMG object with the class ‘image-landscape’.
And code such as ‘img.height’ will not work with jQuery. You may want to change it to img.height()
Thanks,
Alex
Jeff
July 8, 2010
Here’s what I have so far. I’m able to get the initial width and height now (thanks!) but can’t get the click events to fire.
$(document).ready(function() {
var img = $(’#image-landscape’);
var initW = img.width(), initH = img.height();
$(’.controls LI A’).each(function(el, i){
$(el).click(function(e){
alert(’test’);
e = new Event(e).stop();
var newW = img.width(), newH = 0;
switch(el.rel){
case ‘zoomOut’:
alert(’zoomOut’);
newW -= 20;
break;
case ‘zoomIn’:
alert(’zoomIn’);
newW += 20;
break;
default:
newW = initW;
}
var ratio = initH / initW;
newH = newW * ratio;
img.width() = newW;
img.height() = newH;
});
});
});
-
+
Reset
ajaxBlender.com
July 15, 2010
Jeff,
In jQuery, you should process it differently. For example:
$('.controls LI A').click(function(){alert('Link has been clicked.');
return false;
});
Try it and let me know if it is okay.
Thanks,
Alex
Tapestry
January 28, 2011
This looks close to what I am looking for. I need to resize an image width: 507px height: 370px, keeping it centered, depending on the clients resolution. The image needs to scale down depending upon the screen size. Is this possible? Thank you in advance for your help.
rudrax
April 3, 2011
hay, its great!thanks Alex.
John hook
April 12, 2011
hey I’m trying to put this code on the blogger for my blog put I can’t save it because it gives me always an error I’ve put on the top this code.
var newSize = scaleSize(200, 200, 500, 313);
alert(’New Width: ‘ + newSize[0] + ‘, New Height: ‘ + newSize[1]);
function scaleSize(maxW, maxH, currW, currH){
var ratio = currH / currW;
if(currW >= maxW && ratio if(currH >= maxH){
currH = maxH;
currW = currH / ratio;
}
return [currW, currH];
}
is this right or not?
thanks in advance!
emidio
April 13, 2011
“} else if(currH >= maxH){”
change in:
“} if(currH >= maxH){”
else the function do the resize only one side (width or height) if the image is greater then both width and height
Noob
May 5, 2011
Thanks for a great post, and thanks emidio your solution is what made the scaling work for really large images!
Mark
July 20, 2011
Could you provide a simple example showing your script resizing multiple images automatically to any image using a particular class name?
Websoftwares
August 25, 2011
@mark i came up with this it works but on my content sometimes getSize().x or y shows 0.
Anyone can help on that, thanks.
window.addEvent(’domready’,function(){
if(document.getElement(’div.blog_description’)) {
// only run on selected elements else don’t.
var images = document.getElement(’div.blog_description’).getElements(’img’);
//get all images Array.each(images,function(image,index) {
// loop over all images.
var newSize = scaleSize(200, 200, image.getSize().x, image.getSize().y);
// run function to get new sizes
image.width = newSize[0];
// set new width
image.height = newSize[1]
// set new height
})
}
});
ajaxBlender.com
August 31, 2011
Hello Websoftwares.
In your code you have array of images commented, that’s why it’s not working.
educer
September 15, 2011
Thanks for the article and the comments, they were very useful ;)
This works with jQuery:
$(document).ready(function(){
var img = $(”#image-landscape”);
var initW = img.width();
var initH = img.height();
$(’.controls LI A’).each(function(i, el){
$(el).click(function(e){
var newW = img.width(), newH = 0;
switch(el.rel){
case ‘zoomOut’:
newW -= 100;
break;
case ‘zoomIn’:
newW += 100;
break;
case ‘resizeProportionally’:
var newSize = scaleSize(200, 200, $(el.rev).width(), $(el.rev).height());
$(el.rev).width = newSize[0];
$(el.rev).height = newSize[1];
alert(’New Width: ‘ + newSize[0] + ‘, New Height: ‘ + newSize[1]);
return;
default:
newW = initW;
}
var ratio = initH / initW;
newH = newW * ratio;
img.attr(’width’, newW);
img.attr(’height’, newH);
});
});
});
Nirmal
February 18, 2012
can someone help explain, how can i use this code in page onload time? thanks in advance
LookingForPerfectJSScaling
June 27, 2012
Like all the scaling solution i found in the web its totally incomplete and only covers one side of the scaling. This solution ist just for images which are larger in both dimensions. For many cases it doesn´t work. For example if the original image is smaller. Or just one element height or width is smaller.
:(