javascriptjquery

How do I find clientWidth and clientHeight of an image whose element was created?


I have an HTML file field for selecting multiple images for upload. I want to get the clientWidth and clientHeight of the first image. I used jQuery to create image element of the images. I appended the image element to the div where the images are supposed to appear. I tried to find the clientWidth and clientHeight of the image but both the clientWidth and clientHeight of the image were 0. On the other hand, naturalWidth and naturalHeight were correctly determined, How can I get the correct clientWidth and clientHeight of the image given that its element was created through jQuery?

$('#image-upload').change(function(event){
  
    const files = this.files;
    
    if (!files.length) return;
    
    let imageElement = '';
    
    $.each(files, function (index, file){
        const reader = new FileReader();
        
        reader.onload = function (event){
            
            let imgSrc = event.target.result;
            
            imageElement = $('<img>')
            .attr('src', imgSrc)
            .addClass('image')
            .css({width: '100%', 'max-width': '100%', display: 'block'});
            
            
            $('#div-container').append(imageElement);
            
            
            if(index === 0){
                
                $('.image').on('load', function () {
                    
                    let image = document.getElementsByClassName('image')[0];
                    
                    let naturalWidth = image.naturalWidth; //got correct width
                    let naturalHeight = image.naturalHeight; // got correct height
                    let renderedWidth = image.clientWidth; //gives 0
                    let renderedHeight = image.clientHeight; //gives 0
                });
            }
        };

        reader.readAsDataURL(file);
    });
    
});

Solution

  • Instead of relying solely on the image’s load event, you can use requestAnimationFrame after appending the image to the DOM. requestAnimationFrame ensures that the next browser paint cycle is used, allowing the DOM to be updated and the image to be fully rendered.

    By using requestAnimationFrame after appending the image to the DOM and ensuring the image has loaded, you can guarantee that the image is both fully loaded and rendered, which will allow clientWidth and clientHeight to return correct values.

    This works for me :

        img.onload = function () {
            $('#div-container').append(img);
    
            // Only for the first image
            if (index === 0) {
                requestAnimationFrame(() => {
                    const naturalWidth = img.naturalWidth;
                    const naturalHeight = img.naturalHeight;
                    const renderedWidth = img.clientWidth;
                    const renderedHeight = img.clientHeight;
    
                    console.log('Natural Width:', naturalWidth);
                    console.log('Natural Height:', naturalHeight);
                    console.log('Rendered Width:', renderedWidth);
                    console.log('Rendered Height:', renderedHeight);
                });
            }
        };
    

    <!DOCTYPE html>
        <html lang="en">
    
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Image Dimensions</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
        </head>
    
        <body>
            <div class="mb-3">
               <label for="formFile" class="form-label">Select File</label>
               <input class="form-control" id="image-upload" type="file" multiple>
            </div>
            <div id="div-container">
                <!-- Image will be added here -->
            </div>
    
            <div class="result">
                <p id="naturalWidth"></p>
                <p id="naturalHeight"></p>
                <p id="renderedWidth"></p>
                <p id="renderedHeight"></p>
            </div>
    
            <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    
            <script>
                  $('#image-upload').change(function (event) {
                      const files = this.files;
    
                      if (!files.length) return;
    
                      $.each(files, function (index, file) {
                          const reader = new FileReader();
    
                          reader.onload = function (event) {
                              const imgSrc = event.target.result;
                              const img = new Image();
    
                              img.className = 'image';
                              img.style.width = '100%';
                              img.style.maxWidth = '100%';
                              img.style.display = 'block';
    
                              img.onload = function () {
                                  $('#div-container').append(img);
    
                                  if (index === 0) {
                                      requestAnimationFrame(() => {
                                          const naturalWidth = img.naturalWidth;
                                          const naturalHeight = img.naturalHeight;
                                          const renderedWidth = img.clientWidth;
                                          const renderedHeight = img.clientHeight;
    
                                          console.log('Natural Width:', naturalWidth);
                                          console.log('Natural Height:', naturalHeight);
                                          console.log('Rendered Width:', renderedWidth);
                                          console.log('Rendered Height:', renderedHeight);
                                      });
                                  }
                              };
    
                              img.src = imgSrc;
                          };
    
                          reader.readAsDataURL(file);
                      });
                  });
            </script>
        </body>
        </html>