My goal is to create a responsive grid with an unknown amount of items, that keep their aspect ratio at 16 : 9. Right now it looks like this:
.grid { display: grid; grid-template-columns: repeat(auto-fill, 160px); grid-template-rows: 1fr; grid-gap: 20px; } .item { height: 90px; background: grey; }
<div class="grid"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div>
The problem is, that the items won’t scale with the screen size, resulting in a margin at the right site. But when making the grid adapt to the screen size with e.g.: grid-template-columns: repeat(auto-fit, minmax(160p, 1fr))
and removing the height: 90px;
, the aspect ratio doesn’t persist.
Maybe there is a better solution without css grid? (Maybe using javascript)
Answer
You could take advantage of the fact that padding in percentages is based on width.
This CSS-tricks article explains the idea quite well:
…if you had an element that is 500px wide, and padding-top of 100%, the padding-top would be 500px.
Isn’t that a perfect square, 500px × 500px? Yes, it is! An aspect ratio!
If we force the height of the element to zero (height: 0;) and don’t have any borders. Then padding will be the only part of the box model affecting the height, and we’ll have our square.
Now imagine instead of 100% top padding, we used 56.25%. That happens to be a perfect 16:9 ratio! (9 / 16 = 0.5625).
So in order for the columns to maintain aspect ratio:
- Set the column widths as you suggested:
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr))
Add a pseudo element to the items to maintain the 16:9 aspect ratio:
.item:before { content: “”; display: block; height: 0; width: 0; padding-bottom: calc(9/16 * 100%); }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); grid-template-rows: 1fr; grid-gap: 20px; } .item { background: grey; display: flex; justify-content: center; } .item:before { content: ""; display: block; height: 0; width: 0; padding-bottom: calc(9/16 * 100%); }
<div class="grid"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div>