'CSS - How to scale up images with homothety and limits?

I have a list of logos in a flex wrapper:

ul {
  display: flex;
  gap: 10px;
  border-bottom: 1px dashed red;
}

li {
  list-style-type: none;
}

img {
  display: block;
  max-width: 150px;
  max-height: 100px;
}
<ul>
  <li>
    <!-- this one is well-sized (100x100) -->
    <img src="https://via.placeholder.com/200x200" />
  </li>
  <li>
    <!-- this one is too small on x axis (should be 150x60) -->
    <img src="https://via.placeholder.com/100x40" />
  </li>
  <li>
    <!-- this one is too small on y axis (should be 55x100) -->
    <img src="https://via.placeholder.com/50x90" />
  </li>
  <li>
    <!-- this one is too small on both axis (should be 150x100) -->
    <img src="https://via.placeholder.com/125x83" />
  </li>
</ul>

I want every logo to fill as much space as possible in a limit of 150x100px.

I can't use object-fit: contain as it would force every <img> to be 150x100px, and I don't want images to occupy the same space.

I would like to achieve something like this:

enter image description here

Where each logo is never wider than 150px and taller than 100px.

So I've put max-width: 150px and max-height: 100px on the images, but that's not enough.

Because some images are smaller than the display size.

The client can upload any image, and sometimes he can upload a 50x50px image, when the minimum size is 150x100px.

I don't care if the loaded images are smaller than the display size, I want to force their display's width and height.

But if I force it with width: 100% and height: 100%, it will force every image to always be 150x100px:

enter image description here

Is there a way to make every image scale as much as possible in order to occupy a space of 150x100px, no matter their intrinsic size?



Solution 1:[1]

It's not possible to do the wanted result just with the current html, but I've found a hack that uses the svg homothetic scaling capability:

ul {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border-bottom: 1px dashed red;
}

li {
  position: relative;
  list-style-type: none;
}

img {
  position: absolute;
  width: 100%;
  height: 100%;
}

svg {
  display: block;
  width: auto;
  height: auto;
  max-width: 150px;
  max-height: 100px;
}
<ul>
  <li>
    <img src="https://via.placeholder.com/200x200" />
    <svg width="1000" height="1000"></svg>
  </li>
  <li>
    <img src="https://via.placeholder.com/100x40" />
    <svg width="1000" height="400"></svg>
  </li>
  <li>
    <img src="https://via.placeholder.com/50x90" />
    <svg width="500" height="900"></svg>
  </li>
  <li>
    <img src="https://via.placeholder.com/125x83" />
    <svg width="1250" height="830"></svg>
  </li>
</ul>

The trick here is to add an <svg> that has a width and height proportional to the image intrinsic size and greater than the display size (here, I've just multiplied the width and height by ten).

Then we reset the display width and height of the svg with width: auto and height: auto and we contain it with max-width: 150px and max-height: 100px.

Now the svgs have the good size.

To finish, we take the images out of the flow with position: absolute and we scale them to 100% of the parent <li> (which take the svg size).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Quentin D