Arian Kulp's Blog
opinion, insight, and occasional code

Javascript Image Resizing

Monday, April 07, 2008 11:30 AM

I have an ASP.NET project where I need to resize images on the client.  Why would you need to do that?  Well, you don't always know the images you are displaying.  If you are storing the images, or want to pre-fetch them, then you can build thumbnails on the server.  On the other hand, if you just have arbitrary images (most likely user-embedded) you may want a consistent thumbnail size without knowing anything about them to begin with.

I did lots of searching on this topic and never did find exactly what I needed, hence this post.  My end solution relies on a combination of JavaScript and minimal CSS.

If you've ever tried to resize images on the client side, you know how easy it seems (at first).  Just set the height and width attributes of the img element.  What's wrong with this approach?  Well I'm sure you've seen the squashed images that result from this.  If you don't know the original dimensions, you can't calculate the new resized dimensions to maintain the aspect ratio.  In the course of my searching, I came across this older post by Tom Davies.

This works very well, but isn't quite as flexible as I wanted.  For one thing, it only uses one dimension for the thumbnail bounding box.  I wanted to be able to set separate sizes.  I also wanted to prevent the image from sizing large initially as it loads, then "snapping" into its resized form.  This looks funky, but it also proved to ruin layout in Firefox (once it made room for the large format, it never seemed to layout again with the smaller size).  The simple solution to the layout issue is to enclose the img element in a div which is set with overlap: hidden.  This allows the image to load however it needs to but it never takes up more space than its box.

Some things that I learned: you need the actual dimensions of the image in order to calculate the new size.  If you set either height or width (thinking it will allow better layout), the element will then report that number as its dimension.  This makes it imperative that you leave those attributes out of your images.

I also learned that you can't set the display css property to none.  This causes the image to not even be loaded in IE (though it still raises the onload event).  If it isn't loaded, it will return zeroes for dimensions.  Setting visibility: hidden is fine as it preserves layout.  This is what I did, in combination with overlap: hidden so the thumbnail pane would appear blank until it was loaded and resized.

I used one CSS class for thumbnails (in conjunction with overriding the onload event), and a second class to indicate thumbnails that have been sized (to prevent double-work for whatever reason).  You could write a function to enumerate all elements of your thumbnail class if you wanted to once the document completely finished loading, but this worked well for me.  I simply call ResizeImage(this, 50,50) and it passes the element (no calling GetElementById()) and size at the same time.

The function is here:

function ResizeImage(image, maxwidth, maxheight)
{
    if (image.className == "Thumbnail")
    {
        w = image.width;
        h = image.height;
                
        if( w == 0 || h == 0 )
        {
            image.width = maxwidth;
            image.height = maxheight;
        }
        else if (w > h)
        {
            if (w > maxwidth) image.width = maxwidth;
        }
        else
        {
            if (h > maxheight) image.height = maxheight;
        }
                
        image.className = "ScaledThumbnail";
    }
}

The "zero" case is a bit unfortunate, and possibly even ineffective, but is intended to deal with an image that hasn't completed loading yet. It might be better to abort and leave this image alone (without modifying the CSS class), but likely the function wouldn't be called on it a second time.

The surrounding DIV tag can be given a border if desired, but I've had trouble keeping the box at the right dimensions across browsers -- and centering the image within the box for multiple browsers is not an exercise for the faint-at-heart.  This method makes it easy to resize images on the client, but you'll need to decide what to do with it then!




Feedback

# re: Javascript Image Resizing

Arian,

Some of the open source Javascript libraries will let do image resizing without having to worry about many of the cross browser Javascript details.

Check out the jQuery UI project here: http://dev.jquery.com/view/trunk/ui/demos/ui.resizable.html

Simple image resizing is just one of the many things that jQuery gives you.

Chris 4/8/2008 11:35 AM | Chris sutton

# re: Javascript Image Resizing

Good point Chris. There are good libraries out there. Sometimes you need to avoid certain licenses so it's better to come up with your own... If you can use it though, definitely it's better to take advantage of what's out there. 4/8/2008 1:02 PM | Arian

# re: Javascript Image Resizing

Gotcha, seeing gpl in the license could make a some companies nervous. 4/9/2008 7:18 PM | Chris Sutton



Post a comment






 

Please add 2 and 2 and type the answer here: