As far as I know, you have one possibility.
Note: Consider this a hack which probably should not be used in production code.
Percentage values of the margin
and padding
properties are relative to the width of the containing block. This means margin-top
and padding-top
(running along the Y axis) will respond to changes made to the width of the parent (running along the X axis).
In the following example, .child
has a width of 50%
, which is relative to the width of the parent. To have its height respond to the width of the parent, we can simulate a height using the padding-top
property. Now both the width and the simuated height of .child
are relative to the width of .parent
, thus preserving the aspect ratio.
(Try resizing .parent
to see how .child
responds while keeping the aspect ratio.)
.parent {
width: 200px;
height: 150px;
background: orange;
overflow: scroll;
resize: both;
border: 1px solid #999;
}
.child {
margin: auto;
width: 50%;
height: 0;
padding-top: calc(50% * 0.75);
background: yellow;
}
<div class="parent">
<div class="child"></div>
</div>
Now, as anyone will quickly find out, this does not allow for any contents inside .child
. To fix this, you can introduce another nested <div>
named .grand-child
. Make .child
relatively positioned and .grand-child
absolutely positioned inside of .child
.
.parent {
width: 200px;
height: 150px;
background: orange;
overflow: scroll;
resize: both;
border: 1px solid #999;
}
.child {
position: relative;
margin: auto;
width: 50%;
height: 0;
padding-top: calc(50% * 0.75);
background: yellow;
}
.grand-child {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: red;
}
<div class="parent">
<div class="child">
<div class="grand-child">
Hello world
</div>
</div>
</div>