Subscribe to our RSS

How to Resize Image Proportionally using JavaScript

Tags: , , ,

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:

bounding-box

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

sample-image

After the image resize we should get something like this:

resized-image

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.

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.

:(

Nirmal

February 18, 2012

can someone help explain, how can i use this code in page onload time? thanks in advance

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);
});
});
});

ajaxBlender.com

August 31, 2011

Hello Websoftwares.
In your code you have array of images commented, that’s why it’s not working.

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
})
}
});

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?

jared javascript guy

May 5, 2011

Thanks for a great post, and thanks emidio your solution is what made the scaling work for really large images!

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

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!

rudrax

April 3, 2011

hay, its great!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.

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

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 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 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

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

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 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 5, 2010

should be:

scaleSize(120,120,225,300) will result in [120,160]

sorry for the typo.

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

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];
}

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!

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

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.

karev

December 21, 2009

it is possible to make this script resize all the tag in html page automatically ???

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.

jared

November 10, 2009

this is a good article i been looking for one like it, but will it work with my jQuery code?

Leave a comment

Your name

April 20, 2014

Spam protection. Enter result of expression you see in the box below.

10 + 4 =