94

Is there a reliable, framework independent way of determining the physical dimensions of a <img src='xyz.jpg'> resized on the client side?

Pekka
  • 442,112
  • 142
  • 972
  • 1,088

6 Answers6

133

You have 2 options:

Option 1:

Remove the width and height attributes and read offsetWidth and offsetHeight

Option 2:

Create a JavaScript Image object, set the src, and read the width and height (you don't even have to add it to the page to do this).

function getImgSize(imgSrc) {
    var newImg = new Image();

    newImg.onload = function() {
      var height = newImg.height;
      var width = newImg.width;
      alert ('The image size is '+width+'*'+height);
    }

    newImg.src = imgSrc; // this must be done AFTER setting onload
}

Edit by Pekka: As agreed in the comments, I changed the function to run on the ´onload´ event of the image. Otherwise, with big images, height and width would not return anything because the image was not loaded yet.

Pieter VDE
  • 2,195
  • 4
  • 25
  • 44
Gabriel McAdams
  • 56,921
  • 12
  • 61
  • 77
  • That won't work with images that aren't loaded yet. It might be worth adjusting it to work properly for other people stumbling across this answer. – James Dec 22 '09 at 09:45
  • 11
    @Gabriel, I am using this but with an `newImg.onload` function to make sure the image is loaded when I set the width/height. Are you ok with me editing your answer accordingly? – Pekka Jan 02 '10 at 18:19
  • 2
    Just a side note: Chrome/OSX can have problems with cached images where you get 0 as height/width using this technique. – David Hellsing Feb 17 '11 at 20:56
  • 2
    how ca i get return hieght and width...?? because those variable are not getting outside of onload – jack Jun 22 '12 at 11:34
  • @jafar: That's more complicated than I would like to put into a comment. If I were you, I would ask that as a question of its own. Include the source from here, and maybe a link to here in your question. – Gabriel McAdams Jun 22 '12 at 19:35
  • 5
    @GabrielMcAdams, if you add `if(newImg.complete || newImg.readyState === 4) newImg.onload();` at the end of your function it will fix the issue on Chrome/OSX that causes onload not to fire when images are loaded from cache. – Prestaul May 21 '13 at 17:13
  • Note that I tried with a base64 image that was just dragged and dropped and even with those you need to use the onload handler to get the right dimensions. – Alexis Wilke Mar 10 '14 at 08:07
  • I've also seen a problem in Firefox, that the picture dimensions would not be loaded even if the onload function is called. I fixed it with a timeout. – Anders Metnik Oct 29 '14 at 10:54
117

Images (on Firefox at least) have a naturalWidth/height property so you can use img.naturalWidth to get the original width

var img = document.getElementsByTagName("img")[0];
img.onload=function(){
    console.log("Width",img.naturalWidth);
    console.log("Height",img.naturalHeight);
}

Source

Bugster
  • 1,475
  • 1
  • 12
  • 17
  • 4
    This topic is still relevant in 2013. Here's a link with a great workaround for IE7/8: http://www.jacklmoore.com/notes/naturalwidth-and-naturalheight-in-ie/ – BurninLeo Oct 17 '13 at 19:24
  • 5
    This is the winning answer in 2018. Works everywhere. (Per [browser compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement#Browser_compatibility) at MDN.) – 7vujy0f0hy Jul 29 '18 at 07:49
  • 1
    `if (currentYear >= 2022)` You have to use this option. – pouya May 19 '22 at 11:27
3

You can preload the image into a javascript Image object, then check the width and height properties on that object.

Myles
  • 20,860
  • 4
  • 28
  • 37
3
/* Function to return the DOM object's in crossbrowser style */
function widthCrossBrowser(element) {
    /* element - DOM element */

    /* For FireFox & IE */
    if(     element.width != undefined && element.width != '' && element.width != 0){
        this.width  =   element.width;
    }
    /* For FireFox & IE */
    else if(element.clientWidth != undefined && element.clientWidth != '' && element.clientWidth != 0){
        this.width  =   element.clientWidth;
    }
    /* For Chrome * FireFox */
    else if(element.naturalWidth != undefined && element.naturalWidth != '' && element.naturalWidth != 0){
        this.width  =   element.naturalWidth;
    }
    /* For FireFox & IE */
    else if(element.offsetWidth != undefined && element.offsetWidth != '' && element.offsetWidth != 0){
        this.width  =   element.offsetWidth;
    }       
        /*
            console.info(' widthWidth width:',      element.width);
            console.info(' clntWidth clientWidth:', element.clientWidth);
            console.info(' natWidth naturalWidth:', element.naturalWidth);
            console.info(' offstWidth offsetWidth:',element.offsetWidth);       
            console.info(' parseInt(this.width):',parseInt(this.width));
        */
    return parseInt(this.width);

}   

var elementWidth    = widthCrossBrowser(element);
Roman
  • 19,236
  • 15
  • 93
  • 97
2

Just changing a little bit Gabriel's second option, to be more easy to use:

function getImgSize(imgSrc, callback) {
    var newImg = new Image();

    newImg.onload = function () {
        if (callback != undefined)
            callback({width: newImg.width, height: newImg.height})
    }

    newImg.src = imgSrc;
}

Html:

<img id="_temp_circlePic" src="http://localhost/myimage.png" 
style="width: 100%; height:100%">

Sample call:

getImgSize($("#_temp_circlePic").attr("src"), function (imgSize) {
    // do what you want with the image's size.
    var ratio = imgSize.height / $("#_temp_circlePic").height();
});
0

Adding adjustments to Gabriel's second option to help people working with react-grid-gallery.

const [images, setImages] = useState([])

const getImgSize = function (imgSrc, index) {
    var newImg = new Image()

    newImg.onload = function () {
        setImages((images) => [
            ...images,
            {
                id: index,
                src: imgSrc,
                thumbnail: imgSrc,
                width: newImg.width,
                height: newImg.height,
            },
        ])
    }

    newImg.src = imgSrc
}

In useEffect you can call this method

gallery_urls?.map((url, index) => {
            getImgSize(url, index)
        })