Get the real width and height of an image with JavaScript? (in Safari/Chrome)

Get the real width and height of an image with JavaScript? (in Safari/Chrome)

I am creating a jQuery plugin.
How do I get real image width and height with Javascript in Safari?
Following works with Firefox 3, IE7 and Opera 9:
var pic = $(“img”)

// need to remove these in of case img-element has set width and height
pic.removeAttr(“width”);
pic.removeAttr(“height”);

var pic_real_width = pic.width();
var pic_real_height = pic.height();

But in Webkit browsers like Safari and Google Chrome values are 0.

Solutions/Answers:

Solution 1:

Webkit browsers set the height and width property after the image is loaded. Instead of using timeouts, I’d recommend using an image’s onload event. Here’s a quick example:

var img = $("img")[0]; // Get my img elem
var pic_real_width, pic_real_height;
$("<img/>") // Make in memory copy of image to avoid css issues
    .attr("src", $(img).attr("src"))
    .load(function() {
        pic_real_width = this.width;   // Note: $(this).width() will not
        pic_real_height = this.height; // work for in memory images.
    });

To avoid any of the effects CSS might have on the image’s dimensions, the code above makes an in memory copy of the image. This is a very clever solution suggested by FDisk.

You can also use the naturalHeight and naturalWidth HTML5 attributes.

Solution 2:

Use the naturalHeight and naturalWidth attributes from HTML5.

For example:

var h = document.querySelector('img').naturalHeight;

Works in IE9+, Chrome, Firefox, Safari and Opera (stats).

Solution 3:


function getOriginalWidthOfImg(img_element) {
    var t = new Image();
    t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src;
    return t.width;
}

Solution 4:

The root problem is that WebKit browsers (Safari and Chrome) load JavaScript and CSS information in parallel. Thus, JavaScript may execute before the styling effects of CSS have been computed, returning the wrong answer. In jQuery, I’ve found that the solution is to wait until document.readyState == ‘complete’, .e.g.,

jQuery(document).ready(function(){
  if (jQuery.browser.safari && document.readyState != "complete"){
    //console.info('ready...');
    setTimeout( arguments.callee, 100 );
    return;
  } 
  ... (rest of function) 

As far as width and height goes… depending on what you are doing you may want offsetWidth and offsetHeight, which include things like borders and padding.

Solution 5:

There’s a lot of discussion in the accepted answer about a problem where the onload event doesn’t fire if an image is loaded from the WebKit cache.

In my case, onload fires for cached images, but the height and width are still 0. A simple setTimeout resolved the issue for me:

$("img").one("load", function(){
    var img = this;
    setTimeout(function(){
        // do something based on img.width and/or img.height
    }, 0);
});

I can’t speak as to why the onload event is firing even when the image is loaded from the cache (improvement of jQuery 1.4/1.5?) — but if you are still experiencing this problem, maybe a combination of my answer and the var src = img.src; img.src = ""; img.src = src; technique will work.

(Note that for my purposes, I’m not concerned about pre-defined dimensions, either in the image’s attributes or CSS styles — but you might want to remove those, as per Xavi’s answer. Or clone the image.)

Solution 6:

this works for me (safari 3.2), by firing from within the window.onload event:

$(window).load(function() {
  var pic = $('img');

  pic.removeAttr("width"); 
  pic.removeAttr("height");

  alert( pic.width() );
  alert( pic.height() );
});