Search code examples
htmlcssimageresponsive-images

Perfect Image Container: Centered, Aspect Ratio, Shunk and Grown to Fit


From other questions here on SO, I've come to the point where I can maintain the aspect ratio an image, center it in a container both horizontally and vertically, and make it shrink to fit the container. Almost there!!!

What's wrong? I'd like to expand small images, and optionally be able to add a class to the <img> tag i.e. <img class="nogrow" ... /> to turn off the feature of expanding small images.

JSBin

.parent {
  width: 240px;
  height: 160px;
  border: 1px solid black;
  position: relative;
}

.img-container {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;

  text-align:center;
  font: 0/0 a;
}

.img-container .centerer {
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

.img-container img {
  vertical-align: middle;
  display: inline-block;
  max-height: 100%;
  max-width: 100%;
}
<table>
<thead>
  <th>Actual</th>
  <th>Expected</th>
</thead>
<tbody>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/1000x500" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/1000x500" alt="" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/500x600" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/500x600" alt="" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/50x60" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/50x60" alt="" height="100%" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/100x50" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img src="http://placehold.it/100x50" alt="" width="100%" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <th colspan="2">With ".nogrow"</th>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/1000x500" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/1000x500" alt="" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/500x600" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/500x600" alt="" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/50x60" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/50x60" alt="" />
        </div>
      </div>
    </td>
  </tr>
  <tr>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/100x50" alt="" />
        </div>
      </div>
    </td>
    <td>
      <div class="parent">
        <div class="img-container">
          <div class="centerer"></div>
          <img class="nogrow" src="http://placehold.it/100x50" alt="" />
        </div>
      </div>
    </td>
  </tr>
</tbody>
</table>


Solution

  • Try object-fit: contain (and none or scale-down for .nogrow). You shouldn't need any divs at all, just set the dimensions of the image to 100% by 100%.

    <!DOCTYPE html>
    <style>
     td { width:240px; height:160px; border:1px solid }
     img { width:100%; height:100%; object-fit:contain; display:block }
     .nogrow { object-fit:scale-down }
    </style>
    <table>
     <tr><td><img src="http://placehold.it/1000x500" alt="">
     <tr><td><img src="http://placehold.it/500x600" alt="">
     <tr><td><img src="http://placehold.it/50x60" alt="">
     <tr><td><img src="http://placehold.it/100x50" alt="">
     <tr><th>With ".nogrow"
     <tr><td><img class="nogrow" src="http://placehold.it/50x60" alt="">
     <tr><td><img class="nogrow" src="http://placehold.it/100x50" alt="">
    </table>