15

I am using CSS Grid to layout a thumbnail gallery, no Javascript or any other responsive techniques. I would like to set the height of thumbnails to be as its width (1:1) square ratio.
Why? when the page loads I need the thumbnail div's to take space, because now if there is no Image inside the thumbnails div it doesn't take any space.

Here is a Live example: https://www.w3schools.com/code/tryit.asp?filename=FMCULIDQUOBX

Here is the Code:

.container {max-width: 900px;}
.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 15px;
}
.thumbnail {box-shadow: 0 4px 4px rgba(0,0,0,0.50);}
img {width: 100%; display: block;}

...............................

<div class="container">
  <div class="gallery">

    <div class="thumbnail">
      <a href="large-image.jpg">
        <img src="thumbnail-image.jpg">
      </a>
    </div>
    <div class="thumbnail">
      ...... same as above ......
    </div>
    <div class="thumbnail">
      ...... same as above ......
    </div>
    <div class="thumbnail">
      ...... same as above ......
    </div>

  </div>
</div>

The Code above divides the width (900px) into four fractions, and the 4 thumbnails are placed in 1 row. That's why I don't define any width.
If Images don't load, the thumbnail div wont even be visible.
In other words, if you disable images in browser, thumbnail div should take space in a square shape.
How to fix this? Thanks

MEGA
  • 261
  • 1
  • 2
  • 9
  • There is no CSS-Grid method of creating squares based on `fr` units`. – Paulie_D Dec 08 '17 at 11:27
  • 1
    https://stackoverflow.com/questions/1495407/maintain-the-aspect-ratio-of-a-div-with-css – Paulie_D Dec 08 '17 at 11:42
  • 1
    _“when the page loads I need the thumbnail div's to take space”_ - then provide the actual image dimensions via `width` and `height` attributes in the HTML, so that the browser will know what the aspect ratio is upfront ... then it can calculate the _correct_ height according to the width the image is _display with_ before it has loaded the actual image. – CBroe Dec 08 '17 at 11:55
  • use max-* properties – Rajendran Nadar Dec 08 '17 at 12:02
  • 1
    @CBroe I couldn't do that, the layout will break when resizing browser window. – MEGA Dec 08 '17 at 17:26
  • Why would it do that then? – CBroe Dec 08 '17 at 17:46
  • @CBroe here is a live example: https://www.w3schools.com/code/tryit.asp?filename=FMCULIDQUOBX – MEGA Dec 11 '17 at 07:13
  • Nothing breaks, as soon as you add `height:auto` for the images in your CSS. – CBroe Dec 11 '17 at 07:55
  • @CBroe sorry, in previous comment i meant "without defining width". Adding `height:auto` doesn't make the div a square. Try adding that and disable Images in browser. – MEGA Dec 11 '17 at 08:00
  • First of all, who does that? Those users are likely used to pages looking different, so that would not bother me too much. (And if it was just the images failing to load for some other reason, it would still work.) Secondly, with images disabled, a bunch of red squares is not going to help the user much in any case - so adding proper alt attributes is the least thing you should do here. But if the squares are that important, you can switch to the padding-bottom hack, too, if you like, that’s an alternative method to achieve image “placeholders” of the correct aspect ratio/dimensions. – CBroe Dec 11 '17 at 08:09
  • @CBroe on live website its not Red and it does include `alt` attribute. I have tried with padding-bottom with no luck. Will try again with some modification to make it work. – MEGA Dec 11 '17 at 09:15
  • worked with padding-bottom hack as @CBroe suggested. https://www.w3schools.com/code/tryit.asp?filename=FMD1UJKTU72Z – MEGA Dec 11 '17 at 10:51

4 Answers4

14

The solution is to add an invisible square element (zero width and 100% bottom padding) to the grid, set equal height to all rows by grid-auto-rows: 1fr; and then reposition the invisible grid element as well as the first grid element to overlap.

So, your css file should look as the following:

.container {max-width: 900px;}

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 15px;
}

.gallery::before {
    content: '';
    width: 0;
    padding-bottom: 100%;
    grid-row: 1 / 1;
    grid-column: 1 / 1;
}

.gallery > *:first-child{
    grid-row: 1 / 1;
    grid-column: 1 / 1;
}

.thumbnail {box-shadow: 0 4px 4px rgba(0,0,0,0.50);}

img {width: 100%; display: block;}
Mostafa Ghadimi
  • 5,883
  • 8
  • 64
  • 102
12

I'm not sure how to do it with css grid but I know how to make .thumbnail maintain it's ratio.

I learnt this trick a while ago and I use it all the time since then.

.thumbnail{
   position: relative;
}
. thumbnail:before{
    content: ' ';
    display: block;
    width: 100%;
    padding-top: 100% \* Percentage value in padding derived from the width  *\
}
.thumbnail > img{
    position: absolute;
    top: 0px;
    left: 0px;
    bottom: 0px;
    right: 0px;
}
Anatoly Yusufov
  • 121
  • 1
  • 5
8

the simplest solution is to add aspect-ratio: 1 to the css of the child divs (the cells)

your parent div css grid-template-columns: 1fr 1fr 1fr 1fr; creates 4 columns

Adding aspect-ratio: 1 to the css of the children of these columns forces each child to have the same height as width

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
}
.thumbnail {
  aspect-ratio: 1
}


<div class="gallery">

     <div class="thumbnail">
            <img src="image1.jpeg">
     </div>

     <div class="thumbnail">
            <img src="image2.jpeg">
     </div>

     <div class="thumbnail">
            <img src="image3.jpeg">
     </div>

     <div class="thumbnail">
            <img src="image4.jpeg">
     </div>
</div>
RumbleFish
  • 2,216
  • 1
  • 20
  • 17
  • This is wonderful, not sure why it's not upvoted more! – grepsedawk Mar 20 '23 at 19:37
  • 1
    This is a good solution, unfortunately iOS 14 and lower [doesn't support aspect-ratio](https://caniuse.com/mdn-css_properties_aspect-ratio), so I had to go with a different solution. – user19103974 Mar 20 '23 at 20:19
-3

The big advantage is that CSS grid by default applies a similar height to its children.

Option is to restructure the HTML and reduce markup (HTML). You can add height to the .gallery class to make it look more square.

.container {max-width: 900px; margin:0 auto;}
.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 15px;
}
.thumbnail {display:block; box-shadow: 0 4px 4px rgba(0,0,0,0.50);}
img {display:block; width:100%; height: auto;}
    <div class="container">
      <div class="gallery">
          <a class="thumbnail"  href="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
            <img src="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
          </a>
    
          <a class="thumbnail" href="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
            <img src="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
          </a>
    
          <a class="thumbnail"  href="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
            <img src="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
          </a>
    
          <a class="thumbnail"  href="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
            <img src="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
          </a>
        
        <a class="thumbnail"  href="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
            <img src="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
          </a>
    
          <a class="thumbnail" href="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
            <img src="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
          </a>
    
          <a class="thumbnail"  href="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
            <img src="https://static.pexels.com/photos/54278/pexels-photo-54278.jpeg">
          </a>
    
          <a class="thumbnail"  href="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
            <img src="https://static.pexels.com/photos/242276/pexels-photo-242276.jpeg">
          </a>
      </div>
    </div>

    
omukiguy
  • 1,401
  • 3
  • 17
  • 36
  • This does not address the principal point of the question - *" I would like to set the height of thumbnails to be as its width (1:1) square ratio."* – Paulie_D Dec 08 '17 at 12:58
  • 1
    Here is a live example that you can experiment on: https://www.w3schools.com/code/tryit.asp?filename=FMCULIDQUOBX – MEGA Dec 11 '17 at 07:44