Fill a parent div while maintaining a ratio
Using aspect-ratio: 16 / 9; overflow: hidden;
(aspect-ratio
MDN docs) should give you the exact result you're looking for without needing to use the padding trick. Make sure the parent is set to display: grid
or else it may not scale properly.
The aspect-ratio
CSS property is supported by all major browsers (caniuse.com) except Safari, though Safari plans to add support this year. This is the best/correct way to achieve this effect, without having to resort to JavaScript or any hack solutions.
Related questions and answers here on Stack Overflow:
- https://stackoverflow.com/a/66786774/3824249 (very similar to my solution)
- https://stackoverflow.com/a/20593342/3824249 (another CSS-only alternative, though hackier using
position: absolute
for element positioning)
Here is my solution in action:
html, body { height: 100%; }
.parent {
display: grid;
resize: both;
height: 50%;
width: 90%;
border: 2px solid #000;
overflow: hidden;
}
.child {
width: 100%;
max-height: 100%;
margin: auto;
aspect-ratio: 16 / 9;
overflow: hidden;
box-sizing: border-box;
position: relative;
background: #a0522d;
text-align: center;
font-size: 20px;
color: white;
/* using the below to center the text, optional */
display: flex;
align-items: center;
justify-content: center;
}
<div style="padding: 5px 10px; margin-bottom: 10px; background: #f00; color: #fff; text-align: center; z-index: 1;">Resize the block below using the resize controls to see this in action.</div>
<div class="parent">
<div class="child">content that is not images...</div>
</div>
Div that fits into parent and maintains 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!
How to fill a div but maintain aspect ratio for child divs
You already have squared buttons.
The thing you miss is the width of those buttons but it's something you can calculate easily.
The div #menu
has a height of 100vh - 7%
, it means that your buttons should have a height of (100vh - 7%) / 5
.
Their height ise equal to their width, so if they have width: calc(93vh / 5)
they will fill the height of the #menu
.
Therefore, you can simply add #menu { width: calc(93vh / 5)}
I would also remove #main { height: 100% }
, it's not needed.
html, body { margin:0; padding:0;}#container { display:flex; flex-direction: column; background-color: #444; height:100vh; width:100%; margin:0; padding:0;}#top{ background-color: #777; height:5%; width:100%; margin:0; padding:0; }#main{ background-color: #DDD; /* height:100%; not needed */ width:100%; margin:0; padding:0; align-items: stretch;}#menu{ display:flex; flex-direction: column; background-color: #FFF; height:100%; width: calc((93vh) / 5); // Width of the menu = Height of the menu divided by the number of buttons margin:0; padding:0; }.buttons{ display:block; position:relative; height:0; margin:0; padding-bottom:100%;}#button1{background-color:blue; margin:2px 0 2px 0;}#button2{background-color:green; margin:2px 0 2px 0;}#button3{background-color:red; margin:2px 0 2px 0;}#button4{background-color:black; margin:2px 0 2px 0;}#button5{background-color:orange; margin:2px 0 2px 0;}.img-container { justify-content: center; display: flex; flex-direction: row; overflow: hidden; padding:16px;}.img-container .img-to-fit { flex: 1; height: 100%;}
.fill { display: flex; justify-content: center; align-items: center; overflow: hidden}.fill img { flex-shrink: 0; min-width: 100%; min-height: 100%}
#bottom { height:2%; display:flex;}#bottom1{background-color:blue;}#bottom2{background-color:green;}#bottom3{background-color:red;}#bottom4{background-color:white;}#bottom5{background-color:orange;}.bottoms{ height:100%; width:20%; margin:0; padding:0;}
<div id="container"> <div id="top"> </div> <div id="main"> <div id="menu"> <div id="button1" class="buttons"> <div class="img-container"> <img class="img-to-fit" src="parcel.png" /> </div> </div> <div id="button2" class="buttons">
</div> <div id="button3" class="buttons">
</div> <div id="button4" class="buttons">
</div> <div id="button5" class="buttons">
</div> </div> </div> <div id="bottom"> <div id="bottom1" class="bottoms">
</div> <div id="bottom2" class="bottoms">
</div> <div id="bottom3" class="bottoms">
</div> <div id="bottom4" class="bottoms">
</div> <div id="bottom5" class="bottoms">
</div> </div></div>
Make square div fill parent at all time without losing its aspect ratio
Maybe something like this would help:
http://jsfiddle.net/2bg1jzg3/5/
$(".visual").animate({ width: "600px", height: "300px"}, 2000, function () { // Animation complete.});
.visual { background-color:lightblue; position:absolute; overflow:hidden; width:250px; height:600px;}.parent { width:auto; height:100% !important; position: relative; display: block;}.parent .square-child { position: absolute; top: 0; bottom: 0; left: 0; right: 0; background-repeat:no-repeat; background-size:cover; background-position: center; background-image: url('http://lorempixel.com/output/abstract-q-g-850-480-8.jpg'); width: 50%; height: 0; padding-bottom: 50%; margin: auto;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="visual"> <div class="parent"> <div class="square-child"></div> </div></div>
How to make div element auto-resize maintaining aspect ratio?
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>
Related Topics
Background Size Cover Ie11 Not Covering Full Area
How to Target Chrome Only, Not All Webkit Powered Browsers
Background-Size Transition on Hover Causes Chrome to "Shake" Background Image
CSS Select Second Level Elements
Why Do Non-Floating Parents of Floating Elements Collapse
How to Change The Style of: -Webkit-Autofill
Horizontal Navigation with Logo in Middle
Compile Less to Multiple CSS Files, Based on Variable Value
Chang Font Size Only for a Single Character with CSS
How to Create a Button (Or Div) with a Border That Has a Gradient and Has Rounded Corners
CSS - Underline Text But Ignore The Spaces
CSS - Use a Horizontal Scrollbar Only