Search code examples
cssaspect-ratio

Object-fit: contain while maintaining aspect ratio


Assuming I have the following markup:

<div id='container'>
  <div id='content'>
  </div>
</div>

And css:

#container {
   width: 100%;   /* container fills window */
   height: 100%;
   max-width: 1000px;
}
#content {
  width: 100%;
  padding-top: 66%; /* (1.5:1 aspect ratio */
  object-fit: contain;
}

This has the behaviour I want (even without the object-fit) whenever the browser aspect ratio is smaller than 1.5:1. I would like the #container element to always stay completely in view, while also maintaining the aspect ratio.

Is this at all possible in pure css (I do not mind adding extra elements)?

I do not want to use vw and vh because the width of the container is bounded by max-width.


Solution

  • It seems you want something like this:

    body {
      margin: 0;
    }
    #container {
      position: relative; /* Containing block for absolutely positioned descendants */
      float: left; /* Shrink-to-fit width */
      background: red;
    }
    #container > canvas {
      display: block; /* Avoids vertical-align problems */
      max-width: 100%; /* Like object-fit:contain (part 1) */
      max-height: 100vh; /* Like object-fit:contain (part 2) */
    }
    #content {
      position: absolute; /* Take it out of flow */
      top: 0; right: 0; bottom: 0; left: 0; /* Same size as containing block */
      overflow: auto; /* In case its contents are too big */
    }
    <div id='container'>
      <canvas width="1000" height="666"></canvas>
      <div id='content'> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non nulla augue. Vivamus hendrerit arcu id fermentum vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non efficitur eros. Mauris pulvinar tortor eros, vitae mollis est suscipit non. Sed accumsan mi vel odio sollicitudin sagittis. Curabitur euismod justo et lorem suscipit tempus.Fusce enim metus, maximus sed lacinia ut, ultrices eu arcu. Vivamus interdum ex ac justo pretium pulvinar. Integer ornare vulputate ligula nec imperdiet. Sed suscipit nisi metus. Aliquam massa ante, dapibus laoreet mauris et, dignissim malesuada urna. Vivamus eleifend pellentesque nisl vitae laoreet. Phasellus a fringilla mauris. Nunc condimentum dui est, eget lobortis ipsum feugiat dictum. Vivamus ultricies, nisi ac gravida luctus, leo augue pulvinar massa, sit amet dictum eros magna at justo. Vivamus eu felis a ipsum auctor imperdiet. Donec eget bibendum tortor. Pellentesque mollis, orci ac molestie mollis, mi eros commodo magna, ac rutrum tellus ipsum in tortor. Nulla vel dui egestas, iaculis felis id, iaculis sem.Vivamus vel varius magna. Vestibulum vulputate massa quis urna finibus rhoncus. Etiam varius in dui fermentum venenatis. In fermentum enim sed laoreet porta. Proin sit amet auctor sapien, eu dapibus nunc. Praesent malesuada leo nec libero interdum efficitur. Nulla ipsum est, tristique ut malesuada id, blandit at odio. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nullam ac ipsum tristique, feugiat justo eu, pellentesque odio.</div>
    </div>

    It uses canvas with its width attribute set to the maximum desired width, and its height attribute given by the aspect ratio. Then it is styled with max-height: 100vh and max-width: 100% to achieve something like object-fit: contain.

    Since #container has height: auto and float: left, its size will be the same as the canvas.

    Then you can add some content inside an absolutely positioned element with the same size as #container.