53

I've read about various kinds of ways getting image dimensions once an image has fully loaded, but would it be possible to get the dimensions of any image once it just started to load?

I haven't found much about this by searching (which makes me believe it's not possible), but the fact that a browser (in my case Firefox) shows the dimensions of any image I open up in a new tab right in the title after it just started loading the image gives me hope that there actually is a way and I just missed the right keywords to find it.

5 Answers 5

69

You are right that one can get image dimensions before it's fully loaded.

Here's a solution (demo):

var img = document.createElement('img');

img.src = 'some-image.jpg';

var poll = setInterval(function () {
    if (img.naturalWidth) {
        clearInterval(poll);
        console.log(img.naturalWidth, img.naturalHeight);
    }
}, 10);

img.onload = function () { console.log('Fully loaded'); }
Sign up to request clarification or add additional context in comments.

5 Comments

This is very cool to know. The one thing I'd add is if the img has a height or width set either on the image tag or in the CSS, then your method just returns that value, not the natural size of the image. Some browsers support the naturalWidth and naturalSize attributes. You can see that here in this mod of your fiddle jsfiddle.net/jfriend00/rQwD4
@katspaugh Thanks for your comment and the provided demo, it's what I've been looking for! @jfriend00 I knew about the natural size problem, but thanks for the modified example, means less work for me.
Seems to be more efficient if you invoke clearInterval as soon as you get a non-zero value for both naturalWidth and naturalHeight, like how aleemb's solution does it (as opposed to waiting until image is loaded).
You can put the same logic inside the onload function instead of the poll. Also manage errors with onError
interesting, any idea about how much faster can you get the information in average (after which percentage of the loading process)
11

The following code returns width/height as soon as it's available. For testing change abc123 in image source to any random string to prevent caching.

There is a JSFiddle Demo as well.

<div id="info"></div>
<img id="image" src="https://upload.wikimedia.org/wikipedia/commons/d/da/Island_Archway,_Great_Ocean_Rd,_Victoria,_Australia_-_Nov_08.jpg?abc123">

<script>
getImageSize($('#image'), function(width, height) {
    $('#info').text(width + ',' + height);
});

function getImageSize(img, callback) {
    var $img = $(img);

    var wait = setInterval(function() {
        var w = $img[0].naturalWidth,
            h = $img[0].naturalHeight;
        if (w && h) {
            clearInterval(wait);
            callback.apply(this, [w, h]);
        }
    }, 30);
}
</script>

2 Comments

This is a nice jQuery alternative, but should not be the accepted answer as it adds dependency that has not been required by the OP.
Not only that, but it is completely unnecessary. He wraps img in a jQuery, and then takes the first element of that same jQuery.
2

You can achieve this with ResizeObserver

new ResizeObserver((e, observer) => {
  img.remove();
  observer.disconnect();
  console.log(`${img.naturalWidth},${img.naturalHeight}`);
}).observe(img);
document.body.appendChild(img);

See https://codepen.io/noamr/pen/NWOaqjp?editors=1111

1 Comment

Perfect solution to me. I'd never realised ResizeObserver can do this. Much better than the setInterval answers!
0

One way is to use the HEAD request, which asks for HTTP Header of the response only. I know in HEAD responses, the size of the body is included. But I don't know if there anything available for size of images.

1 Comment

I'm not sure that the dimensions of an image is in the HEAD response, and anyway, you could only do this on same-origin request, or if you specifically setup your server to allow cross-origin.
0

There is no way to get the image size until it is attached to the DOM unless you decode the response and check the image metadata, which is explained here: https://stackoverflow.com/a/74710020/7134134

A simpler alternative would be appending the element, getting the required data and removing it immediately:

async function getImageDimentions(src: string) {  
  return new Promise(resolve => {
    const img = new Image();
    img.src = src;
    document.body.appendChild(img);
    img.onload = () => {
      img.remove();
      resolve({ width: img.naturalWidth, height: img.naturalHeight });
    };
  });
}

The whole thing runs asynchronously because of the way browser works.

Edit: Although it does not make much difference, the ResizeObserver callback is executed before the onload event, so it may be a little better to use ResizeObserver.

async function getImageDimentions(src: string) {
  return new Promise((resolve) => {
    const img = new Image();
    img.src = src;
    new ResizeObserver((_e, observer) => {
      img.remove();
      observer.disconnect();
      if (img.naturalWidth) resolve({ width: img.naturalWidth, height: img.naturalHeight });
    }).observe(img);
    document.body.appendChild(img);
  });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.