Div that fits into parent and maintain an aspect ratio

Ok, it looks like it can't be solved by CSS only. If anyone interested, I've put together a React component that does the job (Tests and better README soon, when I have time).

It wraps its children into a div and uses JavaScript to compute the width and height of that div in order to accommodate the available space while maintains the given aspect ratio. It basically stretches the wrapper until one of the sides reaches its maximum.

BREAKING UPDATE a CSS only solution has been found!


The only workaround I managed to achieve so far is to wrap the child element in to svg's foraignObject tag:

const container = document.getElementById('container');
document.getElementById('btn').addEventListener('click', () => {
  container.style.height = container.style.height === '100px' ? '200px' : '100px';
});
body {
  margin: 1rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

button {
  margin-bottom: 1rem;
}


#container {
  background-color: #ffceaf;
  width: 400px;
}

svg {
  background-color: #b8d6ff;
  height: auto;
  width: auto;
  max-width: 100%;
  max-height: 100%;
  overflow: hidden;
}

#content {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  border: solid;
}
<button id="btn">Change parent height</button>

<div id="container" style="height: 100px;">
  <svg width="15000" height="5000">
    <foreignObject width="100%" height="100%">
      <div id="content">
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
        content content content content content content content
      </div>
    </foreignObject>
  </svg>
</div>

This solution has downsides:

  • Browser compatibility (IE/Edge do not support foraignObject properly)
  • It's not a best practice. Including elements from a different XML namespace may cause futher issues(?).

I feel like using JS might be better option here.