How to make div element auto-resize maintaining aspect ratio?
css, html
Solution
The `aspect-ratio` ref property has a good support now so you can use the below:
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
background: gray;
}
.stage {
--r: 960 / 540;
aspect-ratio: var(--r);
width:min(90%, min(960px, 90vh*(var(--r))));
display: flex;
justify-content: center;
align-items: center;
background:
/* this gradient is a proof that the ratio is maintained since the angle is fixed */
linear-gradient(30deg,red 50%,transparent 50%),
chocolate;
}
<div class="stage">
<p>Some text</p>
</div>
Old answer
Here is an idea using viewport unit and `clamp()`. It's a kind of if else to test if the width of the screen is bigger or smaller than the height (considering the ratio) and based on the result we do the calculation.
In the code below with have two variables `cv` and `ch` and only one of them will be equal to `1`
If it's `cv` then the width is bigger so we set the height to `cv` and the width will be based on that height so logically `cv/ratio`
If it's `ch` then the height is bigger so we set the width to `cv` and the height will be based on that width so logically `ch/ratio`
In the `clamp()` I am using `1vh`/`1vw` that I multiple by `90` which is equivalent to your `90%` to have `90vh`/`90vw`
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
background: gray;
}
.stage {
--r: calc(960 / 540);
--cv: clamp(0px,(100vw - 100vh*var(--r))*10000,1vh);
--ch: clamp(0px,(100vh*var(--r) - 100vw)*10000,1vw);
height: calc((var(--cv) + var(--ch)/var(--r)) * 90 );
width: calc((var(--ch) + var(--cv)*var(--r)) * 90 );
max-width: 960px;
max-height: 540px; /* OR calc(960px/var(--r)) */
display: flex;
justify-content: center;
align-items: center;
background:
/* this gradient is a proof that the ratio is maintained since the angle is fixed */
linear-gradient(30deg,red 50%,transparent 50%),
chocolate;
}
<div class="stage">
<p>Some text</p>
</div>
In theory the clamp can be simplified to:
--cv: clamp(0px,(1vw - 1vh*var(--r)),1vh);
--ch: clamp(0px,(1vh*var(--r) - 1vw),1vw);
But to avoid any rounding issue and to not fall into values like `0.x` I consider a big value to make sure it will always be clamped to `1` if positive
UPDATE
It seems there is a bug with Firefox so here is another version of the same code:
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
background: gray;
}
.stage {
--r: calc(960 / 540);
--cv: clamp(0px,(100vw - 100vh*var(--r))*100,90vh);
--ch: clamp(0px,(100vh*var(--r) - 100vw)*100,90vw);
height: calc((var(--cv) + var(--ch)/var(--r)) );
width: calc((var(--ch) + var(--cv)*var(--r)) );
max-width: 960px;
max-height: 540px; /* OR calc(960px/var(--r)) */
display: flex;
justify-content: center;
align-items: center;
background:
/* this gradient is a proof that the ratio is maintained since the angle is fixed */
linear-gradient(30deg,red 50%,transparent 50%),
chocolate;
}
<div class="stage">
<p>Some text</p>
</div>
Problem
I'm trying to have a `div` centered in the screen. This div should have a specific `width` and `height` when it fits in the available window space, but it should shrink to fit when the available window space is not enough, but also, maintaining its original aspect ratio. I've been looking at lots of examples that work for a decreasing `width`, but none that work for both `width` and `height` changes in the window size. Here's my current CSS: ``` * { border: 0; padding: 0; margin: 0; } .stage_wrapper { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; background: gray; } .stage { width: 960px; height: 540px; max-width: 90%; max-height: 90%; display: flex; justify-content: center; align-items: center; background: chocolate; object-fit: contain; /* I know this is for images, it's an example of what I'm looking for */ } ``` And, my current HTML: ``` <div class="stage_wrapper"> <div class="stage"> <p>Some text</p> </div> </div> ``` This is showing a centered `div` that has a fixed `width` of 960px and a fixed `height` of 540px. It should never be bigger than that. Then, if I change the size of my window to have a smaller `width` or `height` than that, the `div` element is successfuly shrinking - except it is not maintaining the original aspect ratio, and that is what I'm looking for. I want it to respond to changes in both `width` and `height`. Is this possible at all?