Home > database >  How to best fit image to a fixed ratio?
How to best fit image to a fixed ratio?

Time:10-25

I have a catalog of photographs most of which have aspect ratio of 4:3. There are a handful of odd ones and it is not feasible to crop those to 4:3 without losing important parts of the pictures.

I want to show all of these photographs, including the few odd-size ones, in a bounding box of the same size for every photo. The bounding box is determined by a div of class col-md-4:

<div class="row">
  <div class="col-md-4">
    <!- the image here: -->
    <img class="img img-responsive" src=" ... " />
  </div>
  <div class="col-md-8">
    <!- other stuff -->
  </div>
</div>

For those images that are already at 4:3, they all show up nicely with the exact same display dimensions, even though the image (file) sizes can be different, eg one can be of 1024x768 and another is 800x600.

For an image that is "too wide", I would like it to be displayed as (where the gray bars represent the background of the bounding area):

enter image description here

For an image that is "too tall", I would like it to be displayed as:

enter image description here

In other words, each odd size image should "choose" its height or width to fit into the bounding box depending on whether it is too tall or too fat. Is this achievable by bootstrap and css?

It may be worthwhile noting that currently, the bounding div has the same width set by bootstrap for every image. The height is determined by the image's aspect ratio. When every photo is at 4:3, then the heights are also all the same. So for odd-size photos, the height has to be locked at 3/4 of the display width.

CodePudding user response:

You can use padding-top and absolute positioning (and a bit of magic) to achieve that:

.imagewrapper {
  display: block;
  position: relative;
  background-color: blue;
  border: 1px solid red;
}

.imagewrapper:before {
  content: '';
  display: block;
  width: 100%;
  /* this is AR of 16:9 calculated 9:16*100 = 56.25 */
  padding-top: 56.25%;
}

.imagewrapper img {
  position: absolute;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
<div class="imagewrapper">
  <img src="https://dummyimage.com/1000x200/000/fff" alt="600x400" />
</div>

<div class="imagewrapper">
  <img src="https://dummyimage.com/600x400/000/fff" alt="600x400" />
</div>

<div class="imagewrapper">
  <img src="https://dummyimage.com/400x600/000/fff" alt="600x400" />
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

If you need another aspect ratio for the container change the padding-top value of .imagewrapper:before. It can be calculated by height / width * 100 (e.g. 9 / 16 * 100 = 56.25 for 16:6 or 4 / 3 * 100 = 133 for 3:4).

How does this work?

The before Element gets 100% width of its parent and a specified percentage-based padding-top value (e.g. 56.25%) which makes it take 56.25% of its width as height which basically makes it a fixed AR box.

The image gets positionied centered inside this box by position absolute, top, left and the transform while its size is contained by height and width auto but max-height and max-width 100%.

You can put this inside roughly anything that changes the width of the outer element and it should work.

Similar behaviour can be achieved using aspect-ratio but this solution works in MSIE and other (legacy) browsers and basically everything from this millennium too.

  • Related