Jack MooreTwitterGithub

NaturalWidth and NaturalHeight in IE


Oct 23rd, 2011  »  8 comments

Getting the naturalWidth and naturalHeight for an image in any browser.


Actual width and height in modern browsers

Modern browsers (including IE9) provide naturalWidth and naturalHeight properties to IMG elements. These properties contain the actual, non-modified width and height of the image.

var 
nWidth = document.getElementById('example').naturalWidth,
nHeight = document.getElementById('example').naturalHeight;

Actual width and height in IE8 and IE7

The naturalWidth and naturalHeight properties are not supported in IE8 or lower. The height and width property will give the apparent width and height after stylesheet and inline styles, inline width and height attributes, and the display property of the image and the image's parent elements have been applied. The simplest way to get the unmodified width and height is to create a new image element, and use it's width and height property.

function getNatural (DOMelement) {
    var img = new Image();
    img.src = DOMelement.src;
    return {width: img.width, height: img.height};
}

var 
natural = getNatural(document.getElementById('example')),
nWidth = natural.width,
nHeight = natural.height;

jQuery naturalWidth() and naturalHeight()

Here is a short jQuery (any version) plugin that adds two methods: naturalWidth() and naturalHeight(). It uses branching to determine if naturalWidth and naturalHeight are supported by the browser. If supported, the method just becomes a getter for the naturalWidth or naturalHeight property. If not supported, the method creates a new unstyled image element and returns that element's actual width and height.

// adds .naturalWidth() and .naturalHeight() methods to jQuery
// for retreaving a normalized naturalWidth and naturalHeight.
(function($){
  var
  props = ['Width', 'Height'],
  prop;

  while (prop = props.pop()) {
    (function (natural, prop) {
      $.fn[natural] = (natural in new Image()) ? 
      function () {
        return this[0][natural];
      } : 
      function () {
        var 
        node = this[0],
        img,
        value;

        if (node.tagName.toLowerCase() === 'img') {
          img = new Image();
          img.src = node.src,
          value = img[prop];
        }
        return value;
      };
    }('natural' + prop, prop.toLowerCase()));
  }
}(jQuery));

// Example usage:
var 
nWidth = $('img#example').naturalWidth(),
nHeight = $('img#example').naturalHeight();

Hey You

Follow me on Twitter, Github, or RSS. Why should you? I'm meticulous and have a lot of free time. Sometimes good things come out of that.

Comments

Gábor5 months agoReply
Thanks a lot for this!
Fyodor4 months agoReply
Thanks for a tip. However the first example has issues with large images on IE. You need to wait for image to actually load even if it is in the cache.
Seth Battin4 months agoReply
Excellent article, thank you. I just implemented your plugin on a project. I am using it in conjunction with the jCrop plugin, which outputs screen coordinates. They were incorrect for any resized image, but now that can be corrected.
Tim Dawson3 months agoReply
Thank you, your simple example has got me out of a hole. Is it possible to test for availability of 'naturalWidth' as one does for 'getElementById' viz: if (!document.getElementById)... I tried: if (document.naturalWidth) { use naturalWidth; } else ( use getNatural function; } but it was ignored even by Firefox(8), which followed the 'else' route
Jack3 months agoReply
You want to check if the property exists specifically for image elements. So your if statement would look something like this:
if ('natualWidth' in new Image) {
Jack3 months agoReply
Forgot to mention that the code above already does this using branching. If naturalWidth/Height is supported, then the plugin is just a wrapper for those native methods.
Anonymous3 months agoReply
Thanks, Jack. I'm using the 'getNatural' function, not the plugin. If I can successfully test for 'naturalWidth I can avoid unnecessary manipulation..
Collette3 months agoReply
Many thanks for this. I was struggling with this for some days and your method really works perfectly. Like Tim Dawson wrote, you got me out of a hole as well. Thanks.

Leave a Comment