Using jQuery to Resize Images After Loading

Programmers

At some point, every web developer comes across the need to fit an image of unknown size into a space on the site they’re building. If all the images will be vertical, you can do this just with CSS; same for all horizontal images. But if the image could be either, you come across an awkward problem of making changes to the size of the image AFTER it loads.

Since this is a fairly common problem, there are many other ways of solving the issue. But the solution below has been the most effective (and easy) one for me to use.

Step 1 – Set up the CSS

We will be using jQuery, of course, but CSS will be in a supporting role. I usually take a Div holder approach, with the width pre-set in CSS.

For example, the image below shows the border (in blue) of my holder Div. The image itself extends outside of the Div, but with my CSS, I’ll be making all the overflow hidden.

jQuery-loading-Before

 

But CSS can help me out a little more. I’ll also set the width of the image to 100% of the holder Div, so that the resulting image will be on the far right (note the image still is a little too tall, but our overflow:hidden takes care of that).

jQuery-loadingAfter

 

The resulting HTML and CSS:

<div id="holder">
<img src="hereissrc.jpg" />
</div>
#holder { overflow:hidden; width:200px; height:200px; }
#holder img { width:100%; height:auto; }

Note the height:auto above; this automatically resizes the height so that the dimensions of the image stay accurate.

Step 2 – What Do You Want?

In our example, we want the image to be resized to fully fill both the height and the width, while getting as much of the image as possible showing. Also, I don’t just want to hide the overflowing image – I also want to center the image in the holder Div.

So we’ve already set the width to 100% in the CSS. If the height is larger than the height of our holder Div, we’ll only need to center the image. Otherwise, we’ll need to change the height and width of the image as well as center it. Confused? Check out the images below.

Option 1: Width is 100%, Height still covers the height (pic 2), so we just center the image vertically (pic 3).

 

Option 2: Width is 100%, Height is too short. Resize height to 100%, center image horizontally.

headerjQuery2

The jQuery Magic

Now that we know what we want, let’s take a look at the jQuery to make it happen. *Make sure you include a link to the jQuery library in your header.

Start with putting everything inside of a “document.ready” function.

jQuery(document).ready(function($) {
//add all the coding here
} 

In this example (that I’m posting in the jsFiddle below), each of my holder Divs have different dimensions so I’m finding each parent’s height and width each time. If all your holder Divs are the same dimensions, take that portion out of the function “imageLoaded” and only find it once at the top.

The first 4 lines below get our heights and widths of the images and of their holder Divs.

function imageLoaded() {
var w = $(this).width();
var h = $(this).height();
var parentW = $(this).parent().width();
var parentH = $(this).parent().height();

//console.log(w + '-' + h + '-' + parentW + '-' + parentH);

//if (w >= parentW){ //always true because of CSS
if (h > parentH){
    $(this).css('top', -(h-parentH)/2);
} else if (h < parentH){
    $(this).css('height', parentH).css('width', 'auto');
    $(this).css('left', -($(this).width()-parentW)/2);
}
//}
}

Next, we’ve got a nice console log note there, in case you want to confirm it’s actually working.

On line 9, the width is always equal to the holder Div because of our CSS, so we’ll just skip that section.

Line 10, we start with the options. If it’s option 1 (see above images), we just need to do a little math to move the image up. Note our CSS has position:relative so that the image will actually move.

If not, on line 12 we start the option 2 (see above images). First, we set the height to height of the holder Div (parentH variable we set earlier), and the width to auto. Remember, setting height or width to auto makes the image keep its appropriate dimensions – we don’t want any skewed images!

And finally line 14, we center the image using a bit a math.

The Math – an image starts at the top left of the div, so any centering of the image inside of the holder Div must start with a “-” (negative) number. Then we’re taking the image width/height (since it’s larger) minus the holder Div’s width/height, and dividing by 2.

Doing it AFTER the image loads

Of course, if you’ve ever tried this before, you know that to use this function we just created, it must be AFTER the image loads; otherwise, the image doesn’t have a width or height yet.

To do that, for each image in our Div “topGallery”, we cycle through and see if the image is loaded. If it is (this.complete), then we call the function “imageLoaded” that we just created, passing the current image in our cycling through to it (using this – line 3 below).

$('#topGallery img').each(function() {
if( this.complete ) {
    imageLoaded.call( this );
} else {
    $(this).one('load', imageLoaded);
}
});

Otherwise, in line 5 above, we use the jQuery function one(). This is like the on() function, except it will only do the action once – the first time. So when the image loads, the first time, it calls the function “imageLoaded” that we created earlier.

Summary & Thanks

The most important things to remember in this example is the CSS. Used in conjunction with jQuery, it handles some of the light lifting so jQuery can focus on the heavy stuff.

A big thanks to user113716 on StackOverflow for his answer to Dee’s question.

And lastly, the full jsFiddle coding:

Comments
  • Sanjesh Nath says:

    Thanks for this. I gave your script a try. My issue was I could see the image being resized on the page as it loaded. It all seemed to fall into place nicely when I put in the “overflow:hidden” on the image container div. Cross browser is also ok so far…fingers crossed. Thanks again.