blacklight
blacklight

Reputation: 33

Maintain aspect ratio of elements within a fluid CSS grid layout

I have a list of div elements in a 4-column CSS grid layout. The div elements are set to 100% width, with a padding-top of 100% to maintain an aspect ratio of 1:1. This is a common technique, as can be seen here: https://stackoverflow.com/a/6615994/7949834

This works in Firefox, but not in Chrome. In Chrome the elements do not take up any space within the grid container. What is the reason for this?

ul {
  border: 2px solid red;
  display: grid;
  grid-gap: 5%;
  grid-template-columns: auto auto auto auto;
  list-style-type: none;
}

div {
  background-color: green;
  padding-top: 100%;
  width: 100%;
}
<ul>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
</ul>

https://jsfiddle.net/ab0asum3/

Upvotes: 1

Views: 5320

Answers (4)

Yuri Friedberg
Yuri Friedberg

Reputation: 11

/* change --grid-aspect-ratio to your aspect ratio*/
:root {
  --grid-aspect-ratio: 16/9;
}

/* Consider using div element for grid */
ul {
  border: 2px solid red;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  list-style-type: none;
}
/* Consider using div element for grid-cell */
li {
  /* set relative position */
  position: relative;
  background-color: lime;
}

li:before {
  content: "";
  display: inline-block;
  padding-bottom: calc( 100% / (var(--grid-aspect-ratio)));
}
/* wrap your content in <div class="grid-cell-inner"> */
.grid-cell-inner {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>
  

It is better to use div elements for grid. Note that you will have to use some inner element for grid cell content and set it`s position to absolute to maintain the same aspect ratio. Dont use % for grid gap, if it is relative to viewport you can use vw/vh units.

Upvotes: 1

Brett DeWoody
Brett DeWoody

Reputation: 62743

There appear to be 2 issues:

  • auto is not a valid value for grid-template-columns - use something like 1fr
  • using a percentage value for the grid-gap when no explicit height has been defined for the li or div

You'll need to use a pixel value for the row gap.

ul {
  border: 2px solid red;
  display: grid;
  grid-gap: 10px 5%;
  grid-template-columns: repeat(4, 1fr);
  list-style-type: none;
  padding: 0;
  margin: 0;
}

div {
  background-color: green;
  padding-top: 100%;
  width: 100%;
}
<ul>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
</ul>

Upvotes: 1

G-Cyrillus
G-Cyrillus

Reputation: 105863

you should use 1fr instead auto to size your columns :

ul {
  border: 2px solid red;
  display: grid;
  grid-gap: 5%;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  list-style-type: none;
}

li:nth-child(4n)~li {
  /* eventually for the gap missing in chrome */
  margin-top: 5%
}

div {
  background-color: green;
  padding-top: 100%;
  width: 100%;
}
<ul>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
  <li>
    <div></div>
  </li>
</ul>


Note: for the square technic, unlike flex it can be made from the grid child and it can allow you to fill div with content and center it example https://jsfiddle.net/ab0asum3/4/

Upvotes: 0

worc
worc

Reputation: 3792

If you open the Chome DevTools and inspect the divs you'll see that the browser is computing their height as 0px. I can't say exactly which quirk or which standard you're breaking here, but if the nested divs don't have a height, they won't impart anything on their parent lis and you won't have anything displayed.

The reason is that Chrome computes the nested div with zero height, which in turn means the parent li will have zero height. That's your why.

Upvotes: -1

Related Questions