Flexbox, responsive grid of square divs maintaining aspect ratio
Solution 1
To maintain your items aspect ratio, a very simple method is to use CSS Viewport units
I modified your pen to see how this units work: http://codepen.io/vladbicu/pen/wMBmOb
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: auto;
max-width: 960px;
width: 80%;
}
.container__item {
align-content: center;
border: 1px solid #333;
display: flex;
flex-basis: 1;
font-size: 3em;
justify-content: center;
margin-bottom: 1em;
// maintain aspect ratio
width: 30vw;
height: 30vw;
}
Hope it helps.
Solution 2
Use the old "padding-bottom" trick for fixed aspect ratio. Extra divs are reqiured though:
.container {
margin: auto;
width: 80%;
max-width: 960px;
}
.container__square {
float: left;
position: relative;
padding-bottom: 50%;
width: 50%;
background: linear-gradient(45deg, #CCC, #000, #CCC);
}
.container__square__item {
position: absolute;
top: 1em;
bottom: 1em;
left: 1em;
right: 1em;
border: 1px solid #333;
background: #FFF;
}
/* clearfix */
.container::after {
content: "";
display: block;
clear: both;
}
<div class="container">
<div class="container__square">
<div class="container__square__item">?</div>
</div>
<div class="container__square">
<div class="container__square__item">?</div>
</div>
<div class="container__square">
<div class="container__square__item">?</div>
</div>
<div class="container__square">
<div class="container__square__item">?</div>
</div>
</div>
Solution 3
Guess you would have to set at least the min-height
to maintain the aspect ration on re-size, if you want to go with a flex-box layout.
Here is a quick and dirty example.
function setCellsMinHeight (parentSelector, cellsMargin, aspect) {
var winWidth = window.innerWidth,
containerList = document.querySelectorAll(parentSelector),
containerArray = Array.prototype.slice.call(containerList),
childMargin = cellsMargin;
containerArray.forEach(function(elem) {
var containerWidth = elem.offsetWidth,
childCount = elem.children.length,
childWidth = (containerWidth - ((childMargin * 2) * childCount)) / childCount,
childMinHeight = (childWidth / 100) * aspect;
for (i = 0; i < childCount; i++) {
elem.children[i].style.margin = childMargin + "px";
elem.children[i].style.minHeight = childMinHeight + "px";
}
});
}
window.onresize = function(event) {
setCellsMinHeight('.container', 4, 100);
};
setCellsMinHeight('.container', 4, 100);
body {
margin: 0;
}
.container {
display: flex;
flex-flow: row wrap;
align-items: stretch;
max-width: 100%;
margin: 0 auto;
}
.content-cell {
flex: 1;
background-color: #ccc;
}
@media (min-width: 801px) {
.container {
max-width: 800px;
}
}
<div class="container">
<div class="content-cell"></div>
<div class="content-cell"></div>
</div>
<div class="container">
<div class="content-cell"></div>
<div class="content-cell"></div>
</div>
Hope it helps.
Carlo
Updated on June 24, 2022Comments
-
Carlo about 2 years
I'm trying to create a 2x2 grid with divs. Some of the divs might contain an image, but it will probably be set as a background, with the option
background-size: cover
.Here's the pen I created: http://codepen.io/qarlo/pen/vLEprq
.container { display: flex; flex-wrap: wrap; justify-content: space-between; margin: auto; max-width: 960px; width: 80%; } .container__item { align-content: center; border: 1px solid #333; display: flex; flex-basis: 1; font-size: 3em; justify-content: center; height: 100%; margin-bottom: 1em; min-height: 300px; width: 47%; }
<div class="container"> <div class="container__item">?</div> <div class="container__item">?</div> <div class="container__item">?</div> <div class="container__item">?</div> </div>
I'd like to force the divs to be squares and maintain the aspect ratio when resizing it. I was mistakenly hoping that this would have been straightforward with flexbox, but unless I'm missing something, I was wrong.
-
Carlo over 8 yearssetting the highest height of the content to all elements wouldn't make them responsive, though. Also, from my example, you can see that the content can also be just a character. The css tricks article is just a tutorial on flexbox, isn't it?
-
Om Komawar over 8 yearsYeah that's what you want right responsive grid with same and square height
-
Carlo over 8 yearsBut it's not enough to just find the highest height, because it wouldn't adjust automatically on resize.
-
Carlo over 8 yearsthis works, is a nice solution, but it's not using flexbox. so I guess flexbox properties are simply not enough (yet?) to solve this problem
-
Carlo over 8 yearsthanks for the script, it seems to work, but again: the main reason I wanted to implement a flexbox solution was to avoid tricky workarounds and rely just on flexbox, but it seems it's still not possible
-
Salman A over 8 years@Carlo there is no flexbox solution in my knowledge. Still you can use flexbox for
.container
and.container__square
instead of floats. I used floats because its old school much like the padding trick. -
Carlo over 8 yearsThis is very nice, but this way it seems that align-content: center doesn't work anymore, does it?
-
Vlad Bîcu over 8 yearsIf you want to vertical align your content, use align-items: center on container__item div. Check this blog post to see the difference between align-content and align-items.
-
Carlo over 8 yearsI actually knew the difference but I was using the other by mistake. Well, this is great and I think is the best solution. Thank you
-
Steven Mouret over 7 yearsFlex-basis do not be 1. Check documentation developer.mozilla.org/en-US/docs/Web/CSS/flex-basis