Home > Back-end >  How can I scale all images to the same dimensional area?
How can I scale all images to the same dimensional area?

Time:04-26

I'm loading in several images. They are various lengths and widths, but I would like for them all to feel as though they are the same "size". So, if one image is 200x100 and another image is 200x400, I would like for them both to scale in such a way that they take up the same amount of space on the screen. If I fix the width to be 200, then the second element is 4 times the size of the first.

For example:

.my_img {
    width: 200px;
}

produces this behavior

How can I use css to fix the area of an image or other element? Where by area, I mean literally length times width. I would like to load in an image of arbitrary dimensions, and scale it (preserving aspect ratio) so that its area is fixed to be a given value.

CodePudding user response:

I don't believe you can do this with CSS. While you can calculate square root with CSS in various ways, getting natural dimensions may be problematic.

You'd have to first establish the smallest image area, then resize each down according to initial proportion, maintaining aspect ratio.

const images = document.querySelectorAll('img');
let smallestArea = 999999999;

const getSmallestImageByArea = () => {
  images.forEach(image => {
    const width = image.naturalWidth;
    const height = image.naturalHeight;

    if (width * height < smallestArea) {
      smallestArea = width * height;
    }
  });
};

const sizeImagesToSmallestArea = () => {
  images.forEach(image => {
    let width = image.naturalWidth;
    let height = image.naturalHeight;
    const area = width * height;

    if (area > smallestArea) {
      const areaRoot = Math.sqrt(area);
      const proportion = areaRoot / Math.sqrt(smallestArea);
      const aspectRoot = Math.sqrt(width / height);

      width = areaRoot / proportion * aspectRoot;
      height = areaRoot / proportion / aspectRoot;

      image.style.width = width   'px';
      image.style.height = height   'px';
    }

    // show hidden images
    image.style.display = 'inline';
    
    console.log('Initial area:', area, '| Final area:', width * height);
  });
};

// wait for images: https://stackoverflow.com/a/60949881/1264804
Promise.all(Array.from(document.images)
  .filter(img => !img.complete)
  .map(img => new Promise(resolve => {
    img.onload = img.onerror = resolve;
  }))).then(() => {
  getSmallestImageByArea();
  sizeImagesToSmallestArea();
});
/* hide images to prevent jumping effect */
img {
  display: none;
}
<img src="https://via.placeholder.com/165x250" />
<img src="https://via.placeholder.com/100x50" />
<img src="https://via.placeholder.com/200x200" />
<img src="https://via.placeholder.com/1900x300" />

CodePudding user response:

Maybe you can try something like this. if you want them to fit on a specific container you have to wrap them and set their height and width and let them fit on it using obejct-fit:cover. This sample have 2 different size images but they fit exactly the way I would do it no matter how big they are. Let me know if this is what you are looking at??

.my_img {
    justify-content:space-around;
    display:flex;
    
}

.my_img > img {
    object-fit: fill;
    height: 300px;
    width: 300px;
    border: 1px solid gray;
    margin: 10px;
    overflow:visible;
    }
<div >

<img src="https://www.kindpng.com/picc/m/227-2275045_daisy-yellow-bloom-frame-flower-border-flowers-transparent.png">
<img src="https://external-content.duckduckgo.com/iu/?u=https://www.clir.org/wp-content/uploads/sites/6/2016/09/Welcome-banner.png&f=1&nofb=1">

</div>

  •  Tags:  
  • css
  • Related