Home » html » Scale, crop, and center an image with correct aspect ratio in HTML and Javascript

Scale, crop, and center an image with correct aspect ratio in HTML and Javascript

Start here

Summary

In this post, I’ll show a technique using HTML and Javascript to properly scale an image of indeterminate size to take up the full space of a parent element that may have a different size, aspect ratio, and orientation. This technique is useful for such scenarios as dynamically generating thumbnails and for displaying a “table of images” where every image is the same size (but the source images aren’t).

Background

In development of my HTML image gallery control, I re-encountered a problem I’ve had with image and video applications. In such applications, the size of the source image (or video) may differ from the size of the target surface it is rendered on. Additionally, the aspect ratio between the source image and target surface may be drastically different. (And in such cases, the image sizes may not be known at design time). The source image may be have a portrait orientation and the surface have a landscape orientation (or vice versa). The user can resize the window and have the content rescale and realign appropriately. Additionally, the view for such content may be to just scale and center it with “bars”. Or the desired view may be to crop the center section out of the image and scale it to fit the entire surface. I’ve seen plenty of image manipulation code bases with implementations of a “compute resize” function incorrectly written. Such implementations often assume the original and desired image size are both landscape orientations.  There’s usually edge case bugs with portrait mode and going between various sizes.

What this post is not about.

  • This is not another post about “how to center an image within a div”. In those cases, you likely have an image of fixed size to be centered positioned within a larger div.
  • If your HTML scenario includes having complete control of the image size, or you know the image size at design time, this post may not be for you.

In both of these cases, go use your favorite image editing tool, and standard CSS to correctly scale and center the image in the DOM using static markup. I’ll cover some static scenarios briefly below to built up to the discussion on a scriptable way to do this for dynamic content.


Simple scenario – static content

Let’s start with a how a web designer or web developer might do something like this with static markup and local content.

Imagine we want to generate a square thumbnail (150×150) of an existing image.  But the image is of a different size – in this case: 300×200. We also want a dark gray border on the thumbnail. The HTML markup may look something like the following to start. (For brevity and readability, I am deliberately in-lining the “style” attribute instead of using a style-sheet.).

<div style="width: 150px; height: 150px; border: thick solid #666666;">
    <img src="tanahlot.jpg" />
</div>

The result will look something like the following:

The image is too big for the div it is hosted in. The obvious thing to do would be to set the width and height attributes to 150px on the image to force it into a square area.  This will lead to a distorted image because the image itself  is not originally square.  To maintain the aspect ratio, the right thing to do is set the width or height, but not both, to be 150px.  But which dimension do you set?  If you set the width to 150px, the height automatically gets scaled to 100px. This will leave 50 pixels of empty space underneath the image.  It won’t be centered.  If you set height to 150px and leave the width attribute unset, then width gets automatically scaled to 225px.  This will render a viewable thumbnail that takes up the entire space, but it won’t be centered either.  The resulting thumbnail will be just a view of the top-left area of the image. We likely would want to have the center area be visible.

We’re going to need to do a few things to get this right.

  • Adjust the width and height attributes of the image such that it maintains its aspect ratio and fits within 150x15o area.  The original aspect ratio of the image is 300:200 (or 1.5).  In this case, if height is fitted to be 150, then width would (150*1.5) == 225px.
  • Use absolute positioning to center the image.  If we scaled the dimensions of the image from 300×200 to 225×150, then we need to move the image to the left by[(image width – div width)/2] == [(225-150)/2] == 37 pixels.
  • Set the overflow style on the parent div to “hidden” so that the extra portion of the image that that doesn’t  fit gets cropped away.

The final adjustments looks like the following:

<div style="width: 150px; height: 150px; border: thick solid #666666; overflow: hidden; position: relative;">
    <img src="tanahlot.jpg" style="position: absolute; left:-37px; width:225px; height: 150px;"/>
</div>

And the result as follows:

Perfectly scaled, cropped, and centered to generate a thumbnail of the original image.  The combination of a negative left offset to position the image and use of the overflow:hidden style allow the iamge to be sized larger than the parent element, but cropped appropriately.

Alternatively, the width of the image can be fitted and the height scaled to match.  Then center vertically instead of horizontally to create a “letterbox” look.

<div style="width: 150px; height: 150px; border: thick solid #666666; overflow: hidden; position: relative;">
    <img  src="tanahlot.jpg" style="position: absolute; top:25px; width:150px; height: 100px;"/>
</div>

The letterbox result looks like this:

Scaling, cropping, and centering when you don’t know the dimensions of the image (until it has been downloaded).

Now let’s discuss how to do a proper scaling when the dimensions of the image are unknown until page load time. Such is the case when showing images delivered by an online photo service. The service may return images at various sizes, aspect ratios, and orientation. But the expectation is that the image is rendered at the same size on the page.

First, one decision has to be made up front: Fitted or Zoomed?

  • Fitted (“Letterboxed”) – the entire image is scaled such that both the width and height of the source fit within the parent. The entire image is visible with no cropping. The letterboxed image is centered within the parent. Empty space (“black bars”) may take up any remaining space. (Similar to watching a widescreen DVD movie on a standard definition TV.)
  • Zoomed (“Pan&Scan”) – The image is scaled proportionally such that only one dimension (width or height) fits within the parent DOM element. The other dimension extends outside the boundary of the surface.

While “letterbox” is appropriate for DVDs, I suggest the “zoomed” mode for most scenarios. Especially for thumbnail creation or when you have a need to make all images look uniform regardless of original dimensions.

Solution

Let me present a worthy helper function that forms the basis for our solution.

function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {

    var result = { width: 0, height: 0, fScaleToTargetWidth: true };

    if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
        return result;
    }

    // scale to the target width
    var scaleX1 = targetwidth;
    var scaleY1 = (srcheight * targetwidth) / srcwidth;

    // scale to the target height
    var scaleX2 = (srcwidth * targetheight) / srcheight;
    var scaleY2 = targetheight;

    // now figure out which one we should use
    var fScaleOnWidth = (scaleX2 > targetwidth);
    if (fScaleOnWidth) {
        fScaleOnWidth = fLetterBox;
    }
    else {
       fScaleOnWidth = !fLetterBox;
    }

    if (fScaleOnWidth) {
        result.width = Math.floor(scaleX1);
        result.height = Math.floor(scaleY1);
        result.fScaleToTargetWidth = true;
    }
    else {
        result.width = Math.floor(scaleX2);
        result.height = Math.floor(scaleY2);
        result.fScaleToTargetWidth = false;
    }
    result.targetleft = Math.floor((targetwidth - result.width) / 2);
    result.targettop = Math.floor((targetheight - result.height) / 2);

    return result;
}

The function above takes 5 parameters:

  • srcwidth – integer width of the source image that we want to scale
  • srcheight – integer height of the source image that we want to scale.
  • targetwidth – integer width of the parent element that we want to fit the image into
  • targetheight – integer height of the parent element that we want to fit the image into
  • fLetterBox – True if we want the “fitted” mode. Otherwise, the function uses the “zoom” mode.

The function above returns an object with the following properties defined:

  • width – new width that should be applied to the image for scaling
  • height – new height that should be applied to the image for scaling
  • targetleft – What the left position attribute of the image should be (can be negative)
  • targettop – What the top position attribute of the image should be (can be negative)
  • fScaleToTargetWidth – bool indicating which dimension was clamped down to fit exactly the size of the parent. (The other dimension was set to keep the aspect ratio correct).

The function above does the math to decide how to scale the image to fit within (or across) a specified area. It does not matter if the image or target are in portrait or landscape orientations. The code above will return the correct result. It also doesn’t matter if the image is “scaling down” (the common case for thumbnails) or “scaling up” for images smaller than it’s parent.  The image will fill the parent. (It would be trivial to modify the ScaleImage function above to have a “not grow” mode.

Now let’s wrap this solution up. The only thing to do is to attach an event handler to the “onload” event of the image to call ScaleImage and apply the result to the DOM objects.  Let’ use one additional helper function to do the work of calling ScaleImage and applying the result.  For brevity, we’ll use JQuery calls to get and set many of the properties and css attributes related to size and offset.

function OnImageLoad(evt) {

    var img = evt.currentTarget;

    // what's the size of this image and it's parent
    var w = $(img).width();
    var h = $(img).height();
    var tw = $(img).parent().width();
    var th = $(img).parent().height();

    // compute the new size and offsets
    var result = ScaleImage(w, h, tw, th, false);

    // adjust the image coordinates and size
    img.width = result.width;
    img.height = result.height;
    $(img).css("left", result.targetleft);
    $(img).css("top", result.targettop);
}

We still need the parent element to still have position:relative and overflow:hidden as part of its CSS styling.  The image element itself need only have the position:absolute tag applied to it. Again, for brevity, I’ll set the onload event callback directly within the markup.

<div style="width: 150px; height: 150px; border: thick solid #666666; overflow: hidden; position: relative;">
    <img src="tanahlog.jpg" style="position: absolute;" onload="OnImageLoad(event);"/>
</div>

And we’re done.  When the page loads, the image downloads and gets instantly scaled to fit.

Visit the sample page at http://www.selbie.com/playground/aspectcorrect/aspectcorrect.htm to see variations of image scaling across different source and target sizes.


74 Comments

  1. bennylondon says:

    Awesome script. Been looking everywhere for one like this. It took me a while to figure out that I needed to change the “var result = ScaleImage(w, h, tw, th, false);” to true to get the letterbox effect – but I’m a bit of a noob at this!

    • selbie says:

      W00t. Someone finally makes the write-up worthwhile. “true” should be the right parameter to indicate letterbox for rendering. Maybe you can sure your code via link on jsfiddle.net so I can take a look.

  2. Excellent script! Thank you very much Selbie.
    I have a blog on blogger and I came to the same problems trying to print thumbnails as you perfectly describe in this post.
    I’m right now in the process to adapt your script because I take the images from feeds and I have dynamic html inside javascript, but I think I got it. Visit http://palabrapensada.blogspot.com/ to see the results when it’s done. Thank you!

    • selbie says:

      Cool. I finally got around to checking your site out. Looks nice and I see you got the ScaleImage code inlined in your HTML. I assume it’s the top-nav with the 4-square image panel that’s making use of this. Good job.

      • Yes, that’s right, I’ve learned a lot to change my blog’s layout but it’s fun. Thanks for your help, I was really hoping for more posts on your site. Count on me for reading them 🙂

  3. Omar Willey says:

    I’m still getting used to the WordPress thing and my PHP/Javascript skills are feeble, so this is great help.

    I’ve been using a theme that uses the ‘post-thumbnails’ function for headline articles but I’m having trouble outsmarting the Loop, to make the thumbnails scale with the code. It’s a little like Gustavo’s problem above.

    Anyway, I do appreciate your post. I hope I speak for hundreds of other silent folks to tell you how cool it is to offer us such things. 🙂

  4. Les says:

    This is really great and just what I’ve needed. It works wonderfully in IE9 and FF, but I’ve reverted to IE8 for testing and found that I’m getting:
    ‘undefined’ is null or not an object

    and it’s pointing to this part:
    img.width = result.width;

    Any thoughts on how to correct this? I’ve tested it on IE8 on multiple computers and got the same results. Thanks.

    • selbie says:

      Hi Les,

      That’s really odd. I though I had tested all this on IE 8. When you go to this page and interact with the buttons, does the script still crash? Have you tried using the F12 tools on IE 8 to debug and figure out if “img” or “result” is the invalid object? It’s entirely possible that the initialization of “img = evt.currentTarget” is incorrect on IE and needs to be set to one of the other event properties.

      Let me know if that test page link above doesn’t work on IE 8. I’ll investigate on IE 8 in a few days when I get IE 8 installed on a VM. If you have a link to a page of your own that is crashing on IE 8, that will be helpful too.

      Let me know, and I’ll get back to you soon.

      jrs

      • Les says:

        Thanks for the quick response. I did use F12 tools on IE8 and the error pointed specifically to the “img.width = result.width;”. I’m guessing it needed a width and heigth first or else it throws a null.

        Interestingly enough, the code on your test page works as it should, but when I use the code as given in this post, it does not. I’m not real good with Javascript so I wasn’t able to figure out why it worked on your test page, but not as given.

        My test page for this is: http://www.techlandhouston.com/TESTaspectratio.asp

        Gustavo’s code worked for me in IE8 though. I noticed his zooms into the image more than yours does. It’s not a complaint, just something I noticed.

        Thank you so much again for this function. I’ve been needing something like this for many many many years. 🙂

    • Les, I have this code working fine (with minor changes) on my page with IE 7 through 9, Firefox, Chrome, Opera, etc. You can check the source in http://palabrapensada.blogspot.com/

      function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {
      var result = { width:0, height:0, fScaleToTargetWidth:true, targetleft:”0px”, targettop:”0px” };
      //
      if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight targetwidth);
      if (fScaleOnWidth) {fScaleOnWidth = fLetterBox;}
      else {fScaleOnWidth = !fLetterBox;}
      //
      if (fScaleOnWidth) {
      result.width = Math.floor(scaleX1);
      result.height = Math.floor(scaleY1);
      result.fScaleToTargetWidth = true;
      }
      else {
      result.width = Math.floor(scaleX2);
      result.height = Math.floor(scaleY2);
      result.fScaleToTargetWidth = false;
      }
      result.targetleft = Math.floor((targetwidth – result.width) / 2);
      result.targettop = Math.floor((targetheight – result.height) / 2);
      return result;
      }
      //
      function hl_img_onload(hlimg) {
      // Rewrite width/height properties because issues with IE 8 (delay loading img, size default to 28×30).
      var t = new Image(); t.src = hlimg.src; hlimg.width = t.width; hlimg.height = t.height;
      //
      var result = ScaleImage(hlimg.width, hlimg.height, 165, 165, false);
      hlimg.width = result.width;
      hlimg.height = result.height;
      hlimg.style.left = result.targetleft + “px”;
      hlimg.style.top = result.targettop + “px”;
      hlimg.style.visibility = ‘visible’;
      }

      • Les says:

        Gustavo,

        I pulled the code off your page and it worked. Thank you so much for that! As I noted above, your code has the photo zoomed in more than the original code meaning, it’s not shrunk all the way to the images shortest edge…..

        Ahhhh… I just noticed that is because my div is set at 150×150 and in your code, you’re setting the result as 165×165. Got it.

        A big thank you to you and to Selbie. This function is just perfect.

      • Les says:

        P.S. – My page using Gustavo’s code is:
        http://www.techlandhouston.com/TESTaspectratio2.asp

      • Les says:

        One more question Gustavo: Is there anyway to not have the width and height of the parent hardcoded?

      • I’m glad it worked, Les.
        I just simplified Selbie’s code because I have fixed DIVs and I didn’t wanted to deal with this, but Selbie already put some code to get the parent sizes and not hardcode it like I did:
        var tw = $(img).parent().width();
        var th = $(img).parent().height();

    • selbie says:

      I believe the issue is in your event handler for onload. Event callbacks in IE8 and earlier aren’t explicitly passed an “event” object as a function parameter. Instead, you just reference the global object, “window.event”.

      Change the top of your function to look like the following such that “img” gets properly initialized.

      function OnImageLoad(evt) {

      var img;
      if (evt && evt.currentTarget) {
      img = evt.currentTarget;
      }
      else {
      img = window.event.srcElement;
      }

      More details here:
      http://www.javascriptkit.com/jsref/event.shtml

      • Les says:

        That did it selbie. Thanks so much for that extra bit of code; you should update it in the post for future visitors.

        Thanks again for this great piece of highly useful javascript and for the quick response from you and Gustavo. 🙂

  5. Mike Ellis says:

    This is exactly what i was looking for. Thank you very much for providing this tutorial!

  6. selbie says:

    I’m glad to hear it was helpful for you.

  7. Ricardo says:

    this is what i needed.. thanks a lot !!

  8. Selbie,

    I cant seem to get it to work, I even threw that last snippet in about ie8, but i am using the image as a link. so I have an img src in an anchor tag, would that be screwing me up? should I post the jscript in the header or body (I tried both)… would JSTL be tossing me up?
    html:

    css:
    #pic{
    width:150px;
    height:150px;
    border: thick solid #666666;
    overflow: hidden;
    position: relative;
    }

    • Ognjen Knaus says:

      You should just find parent’s parent like this:
      var tw = $(img).parent().parent().width();
      var th = $(img).parent().parent().height();

      and it will work if img is wrapped in tag

  9. html didnt come thru:
    div id=”pic”>
    a href=”files/${id}/${id}${dn}”>img src=”files/${id}/${id}${dn}” style=”position: absolute;” onload=”OnImageLoad(event);”>
    /div>

  10. Marc says:

    This has been something very useful ! It took me several hours (half of them because I read wrong about the Letterbox true/false and forgot I changed it in the code). The other half it took me to try and get the Featured Image in WordPress to show this effect.

    This is how I used it in my WordPress template, where a Featured Image from a random post that has the Tag ‘shown’ is taken. The image is then zoom-scaled using the above code.

    1, ‘orderby’ => ‘rand’, ‘tag’=> ‘shown’ ); $rand_posts = get_posts( $args );
    foreach( $rand_posts as $post ) : setup_postdata($post); ?>
    ID ), ‘single-post-thumbnail’ ); ?>
    <img src="” style=”position: absolute;” onload=”OnImageLoad(event);” />

  11. Bob says:

    Thanks for the example–very helpful!

  12. rafableRafa says:

    Awesome, thank you, saved my day!

  13. Kari says:

    Can you ‘crop’ to an oval shape this way? So there is a border or even no border and it just have the background disappear where the corners would be?

    • selbie says:

      Hi Kari,

      There are different techniques for this, but the obvious approach would to do the following:

      1. Crop/resize the source image to a rectangle as per the solution discussed in this blog post.
      2. Overlay a PNG image that matches the background color of the webpage. The PNG file contains a completely transparent oval in the center. The rest of the PNG image is a color that matches the background color of the web page. (That is, and image that is it’s an elliptical “hole”). Use the “z-index” style setting in CSS or inline such that the overlay image is on top of the source image. Make sense?

  14. Bethany says:

    Thanks so much! This is exactly what I was looking for.

  15. Ralph says:

    Hi John, could you please let me know if you’ve released this code with any particular software license? Thanks!

    • selbie says:

      Hi Ralph,

      For the JavaScript code pertaining to image scaling, in the above blog post, the code is provided “as is” with the right to use or extend granted to anyone choosing to use it.

      Attribution back to me is appreciated whenever possible, but not required.

      • selbie says:

        Of course, if your particular situation requires a specific license model, we can likely come to an arrangement. That is, if you actually want to pay for the code, I’ll sell it to you for whatever you think it is worth. 🙂

  16. Ignacio Prado says:

    I am trying to adapt this code to a WordPress site and am getting some inconsistent results. Depending on the connection speed, browser, and some other factors I haven’t diagnosed yet, some or all of the images don’t resize (or they do resize but don’t recenter).

    You can see it here:

    http://ignacioprado.net/test/jason_test/#.ULafDIfhrfV

    The relevant adaptation of the script is here:

    http://ignacioprado.net/test/jason_test/wp-content/themes/gridstyletheme-child/js/printeresting_script.js

    Does this just have to do with me not queueing up the script correctly in a WordPress environment? I am pretty new to the framework and web development generally.

    • selbie says:

      Hi Ignacio,

      I don’t know what the issue is, but from the code you have shared, it appears you have the ScaleImage function commented out:

      // compute the new size and offsets var result = ScaleImage(w, h, tw, th, false);

      In any case, I would suggest making sure you are scaling the image on the “loaded” event for the image (not the document). If you are certain of that, then add some console.log() statements to see what sizes the images are getting scaled to and from. Good luck.

      • Ignacio says:

        Thanks for the prompt reply.

        There is a line break between that comment and the assignment statement. Did you copy and paste the code in a way that would lose the line breaks ?

        I am binding the resizing script to the loading of each image (using jQuery). It’s a hard issue to debug with console.log because the problem varies across browser and connection quality.

      • selbie says:

        Ok, I see that now. But when I look at your site, I don’t know how to discern what the problem is.

        Do you have a minimal example that demonstrates the problem (that you can host on another page and share the link) ?

  17. Artur says:

    Thanks!

  18. Hangs says:

    Thank you this is helpfull

  19. Greg Scowen says:

    Thanks. Script worked flawlessly out of the box and will definitely be used in a hybrid WordPress/custom site I am currently working on (not the site in sig).
    Much appreciated.

  20. Steve says:

    Awesome script! im using this on ny jquery mobile website.However just notice a problem on ipad/iphone (iOS / safari) Works fine on the first image load but then after I get a blank. Suspect it’s caching is there are way to force a reload or someway to overcome caching

    • selbie says:

      It’s known to work fine on both my ipad and Mac. Can you share a URL to an example of what you are referring to?

      • Steve says:

        Hi. After some research I found that some browsers in particular safari ignore the image onload function if the image is cached. Only the window.onload funtion works reliably. So I just applied an ID tag to the image and rejig the OnLoadImage(IDtag) function to read the ID tag and place the function in window.onload. It works fine now from iPhone and iPad. Haven’t tested it on the other mobile devices…..yet!

  21. Tarak says:

    Thanks selbie, saved my day thats exactly what i wanted… We have to handle dynamic images uploaded by users. (may be getting smaller images than parent element). Edited your script by adding following lines

    if (srcwidth < targetwidth) { result.width = srcwidth; }
    if (srcheight < targetheight) { result.height = srcheight; }

    before

    result.targetleft = Math.floor((targetwidth – result.width) / 2);
    result.targettop = Math.floor((targetheight – result.height) / 2);

    in ScaleImage function to center smaller images in the parent box.

  22. Wesley says:

    Occasionally the script distorts the images on load, but when refresh the images are resized correctly. Anyone have this issue? Is there a solution?

    • Gustavo says:

      What browsers did you tried? This happens on Firefox and Chrome too? With IE 8 I had problems with the onload of the image that required to rewrite width/height properties before using the ScaleImage function. You can check my blog http://palabrapensada.blogspot.com

      function hl_img_onload(hlimg) {
      // Rewrite width/height properties for IE:
      var t = new Image(); t.src = hlimg.src; hlimg.width = t.width; hlimg.height = t.height;
      var result = ScaleImage(hlimg.width, hlimg.height, 165, 165, false);
      hlimg.width = result.width;
      hlimg.height = result.height;
      hlimg.style.left = result.targetleft + “px”;
      hlimg.style.top = result.targettop + “px”;
      hlimg.style.visibility = ‘visible’;
      }

      • Ognjen Knaus says:

        No, this happens on FF too (haven’t been testing Chrome much).
        It doesn’t happen always, just sometimes. Maybe depending on the load time or something?
        Seems to me that it happens to larger images.

  23. dw817 says:

    Thank you ! This was most helpful. I will be applying your coding soon.

  24. Johnny says:

    Thanks! Can’t belive how easy it was.. 😀

  25. Eric says:

    The ‘uploader’ I am using, (http://html5demos.com/file-api) is adding the image to the background image.

    How can I get your code to scale it?

    • selbie says:

      You may not need my code to scale it. Just add “background-size: cover;” to your div style. I tried it out with Firebug on your page and it seems to work fine.

      Check this article out: http://www.css3.info/preview/background-size/

      • Eric says:

        Yep – tried that. The drag and drop causes that property to be ‘crossed-out’ in WebKit. Usually that is the case when it is over-ridden by a following instance of the same property. However, I don’t see it re-applied anywhere in WebKit.
        So, what I did is to manually add it back in again in WebKit, and viola! It resized as expected.

        That means the real question is why the drag-and-drop is killing that property – which of course has nothing to do with your code. 🙂

  26. San Luap says:

    Nice script. How can I use this without the event argument? I would like to do something like $(this).scaleImagesNow(); How can I do this?Can’t get it to work.

  27. Mack Audena says:

    Just spent tons of money getting this social-network-type site created and the developers did not give us the crop function. When I brought it up, they wanted to charge something we could no longer afford. Trying to find a turnkey software for what Selbie did here. Can anyone tell me if one exists. If one does not, can sokeone tell me what to copy and paste and where to insert it in my programming. Thanks a lot, in advance.

    • selbie says:

      Mack,
      The blog post discusses how to scale an image down proportionally within the browser after it has already been downloaded. Is that what you want? Or are you looking for a feature where a user uploads a photo and then is presented with a UI control to crop a section from the uploaded picture (ala Facebook)?

  28. OBJECTIVE:
    I Just struggled a lot to get a image gallery going in a custom wordpress theme where the image is also linked with a the_permalink(). While being perfectly fitted to an item container element that is being looped through the wordpress loop and generated at different sized using isotope library and nth-child css. Basically structure wise:
    ~~~wordpress loop code start~~~

    <a href="”>
    <img src="” />

    ~~~wordpress loop code end~~~

    ISSUES:
    My issues were on inspect element looking at consle: “OnImageLoad is not defined”. Then “Property ‘$’ of object [object Object] is not a function”. Then the images disappear completely.

    SOLUTION:
    1.) Put the two functions provided above OUTSIDE of your document.ready area in your javascript file, if you have been coding all your jquery inside a $ or jQuery(document).ready(fucntion) area, then it will work.

    2.) If you then get a “Property ‘$’ of object [object Object] is not a function” error in your console, go and change the “$” signs in the jquery snippet in the tutorial above to “jQuery”. There are 6 of them. Replace them. Refresh.

    3.) If your images disappear its because selbie’s jquery is looking for .parent() element with ends up being the ‘a href’ link which has a height and width of ‘0px’. so just duplicate the .parent() so that both instances of it now looks like this:
    var tw = jQuery(img).parent().parent().width();
    var th = jQuery(img).parent().parent().height();

    Thank you so much Selbie! I cant tell you how many nights I wake up screaming thinking out how I would manually go about get the aspect ratio of an image to fit nicely in every situation.

    • selbie says:

      You wake up screaming in the night? 🙂

      I am glad to see it worked out for you. The ScaleImage function is the core algorithm. I expect most developers will need to tweak the application of this function to the way their page and elements are loaded. (i.e. the OnImageLoaded callback may not work for everyone’s environment).

      • Haha, yea I do. The algorith seems to just have broken and I’m getting a “Uncaught ReferenceError: OnImageLoad is not defined (index):181
        onload” error. What is causing this? Is there another way to launch the function OnImageLoad?

  29. notts says:

    Great script, just wondering if it would be possible to use minimum and maximum values on one side of the parent.

    For example with fLetterBox set to true and a container with :-

    width: 300px; min-height: 300px; max-height: 450px;

    I’m sure would provide more aesthetically pleasing results for both unknown portrait and landscape images.

  30. monkey says:

    Hi – I have some problems – am a newbie and my bkgrd pic is waaay tooo big. – can someone tell me where to place the letterbox or zoom code please. (& is it just zoom of fzoom)
    Do I put it at the top in my hmepage code or in the style.css – or make a new php in my hosting account filemanger and drop it in there –
    Do I then place it in the wp-content, theme, my child theme folder?

    it is always great to have someone with passion give some code to help – but no-one thinks of us poor newbies to let us know exactly where to place it and in which file. I have been stuck on this for a week searching google for answers – getting code but not where to place it!

    2. Where is the code for the pages! —

    3. My header margin where I have my page title is waay too wide – what is this called so I can change it pls — My homepage is fine but I can’t find the codes for the pages! – I was given my site as is and am learning my way around and coding – I wish to change the header for each page I create but I can only change the subtitle I.E. – http:// (homepage)buyredbook — becomes http://hompage/buybluebook —- I want to change red book to blue book to yellow book so that each page header that is clicked on in my list has the relevant header . I know buy red book is my site name and is the title header on my homepage – but why do I have to have it the same on every page ?

    Also there are other things – so knowing where the code gets put for the pages would be good – even if they go into various pages – where to look — no good doing inspect element as it just shows me that it comes mstly from my homepage code. —

    hope you can help. thanks alot

  31. selbie says:

    Hi Monkey,

    I’m not sure I can solve all your issues.

    Sometimes the simplest solution is to just resize the picture to the appropriate size with a tool such as Windows Paint, Paint.NET, Photoshop, or Gimp and then just re-upload it to your website. Or just use the appropriate width/height attributes in CSS or directly on the tag to get the image to be the size you want.

    The post I wrote above is for a more advanced scenario where the image size and it’s aspect ratio is not known in advance, but needs to fitted within a rectangular region. It’s really an advanced issue. But if you feel it applies to your situation, I recommend visiting the sample page: http://www.selbie.com/playground/aspectcorrect/aspectcorrect.htm

    You can right click on the page to “view source” to see how the ScaleImage function is integrated into the HTML.

    You may want to try posting your question(s) on stackoverflow.com. But I’ll warn you – as you have written your post above (poor grammar, overloaded questions, without any code showing what you have already tried), it will likely get voted down. Ask concrete well formed questions with code samples demonstrating what you have tried. You get better answers that way.

  32. ScottN says:

    This looks really interesting but I am not quite sure how to use it without an event. I am trying to scale images that I am loading like this:

    document.getElementById(picName).style.cssText = ‘background-image:url(img/test.jpg)’;

    So I am not sure how to call ScaleImage with this kind of info. Do I load it first?

    Thanks for the wonderful site.

  33. selbie says:

    ScottN – I don’t know if it can be done like that.

    Consider using nested overlapping DIV elements using “absolute” and “relative” position styles as appropriate. One for the background image, and the other for the content of “picName”.

  34. doug says:

    Hi, if I want a smoothe scrolling slide show or video show like wowslider how would i move the image now appearing over the small one, to a fixed point above and the same for all thumbnails whether 5 or 50? I hope for code that will allow me to add as many thumbs as i need and have them appear in a table above the thumbs.

    Thanks! I would prefer an email response if that is allowed, thanks !!

    • selbie says:

      I am not sure I understand the question. But I once prototyped a slide show effect. Basically used jQuery for the sliding animation. And then used a div element with overflow:hidden attribute. So logically, the images were positioned within the div, but the div was only large enough to show one element a time. When the timer fired to scroll to the next image, the jquery animation would kick in to trigger the image scroll.

  35. Hello,

    I love this fix and had it working on a test page of mine. I have since tried it out on another page in the same test site but the width and height don’t set on the image.

    The image seems to load for a split second and I can see the correct src in the console, but the width and height are both set to 0 on the image so nothing loads.

    Do you know any reason why this might be happening?

    Thanks

    Damien

    • Typical. The second I post my question, I figure out what is wrong!

      Basically, my div that had set the width/height styles were not around the image, but around a link surrounding the image.

      Once I moved the div to the correct location (surrounding the image) it fixed my issue

  36. XhuaChen says:

    Hi, thanks for sharing!

    However, I found that when img src is assigned a new value and img load event is trigged again, the script couldn’t scale right again.
    I suggest you change the function as below,

    function OnImageLoad(evt) {

    var img = evt.target;

    // what’s the size of this image and it’s parent
    var w = $(img)[0].naturalWidth; //I change this
    var h = $(img)[0].naturalHeight;
    var tw = $(img).parent().width();
    var th = $(img).parent().height();
    ….

    Use target instead of currentTarget. And Change height to nuturalHeight, or you will get the height of the last scaled value of the old image.

    Thanks again.

  37. Pankaj says:

    I have an error…compilation error ) expected error…but i checked many times, there is no mistake in syntax…

  38. vidya says:

    how should i use this code for dynamic images

    • selbie says:

      What do you mean by “dynamic image”? When you get the onLoad callback that the image has finished downloaded, invoke the ScaleImage function as apporpriate.

  39. […] Nota2. La fuente, y explicación, de la función de escalamiento de imagen proviene de Aquí. […]

Leave a reply to Eric Cancel reply