CSS Grid fixed height and variable width
Asked Answered
C

3

10

I'm trying to make a gallery of images using CSS Grid. I need something like this:

THIS

But all can achieve is this JSFiddle.

Problem is, that DIVs take up all the remaining space, and I don't want that.

#gallery {
  background: #cfc;
  padding: 32px;
  display: grid;
  grid-auto-rows: 350px;
  grid-template-columns: repeat(auto-fit, auto);
  grid-gap: 10px;
}

.cell {
  background: #fcc;
}

.cell>img {
  height: 100%;
}
<div id="gallery">
  <div class="cell">
    <img src="http://via.placeholder.com/350x500" />
  </div>
  <div class="cell">
    <img src="http://via.placeholder.com/250x150" />
  </div>
  <div class="cell">
    <img src="http://via.placeholder.com/150x150" />
  </div>
  <div class="cell">
    <img src="http://via.placeholder.com/370x150" />
  </div>
</div>
Citarella answered 27/4, 2018 at 21:28 Comment(5)
Should the 500px-tallimage scale down to 150px tall?Amsden
because the grid is defined for the cell not the imageLeer
why not using flexbox instead?Grin
Your grid shall have 5 columns. And some of cells span two columnsScreenplay
Ok, so I ditched that idea, since it requires a lot of trickery or libraries to achieve.Citarella
D
1

Look at the following Code:

.parent {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 8px;
grid-row-gap: 8px;
}

.div1 { grid-area: 1 / 1 / 2 / 3; }
.div2 { grid-area: 1 / 3 / 2 / 6; }
.div3 { grid-area: 1 / 6 / 2 / 10; }
.div4 { grid-area: 2 / 1 / 3 / 4; }
.div5 { grid-area: 2 / 4 / 3 / 8; }
.div6 { grid-area: 2 / 8 / 3 / 10; }

.box {
  background-color: #444;
  height: 150px;
}
<div class="parent">
<div class="div1 box"> </div>
<div class="div2 box"> </div>
<div class="div3 box"> </div>
<div class="div4 box"> </div>
<div class="div5 box"> </div>
<div class="div6 box"> </div>
</div>
Defer answered 28/5, 2022 at 12:4 Comment(0)
R
0

Pure CSS solution can be found in this jsfiddle

HTML

<div class="wrap">
    <div class="flex-c">
        <div class="flex-i big"></div>
        <div class="flex-i red"></div>
        <div class="flex-i big green"></div>
        <div class="flex-i green"></div>
        <div class="flex-i red"></div>
        <div class="flex-i blue"></div>
        <div class="flex-i green"></div>
        <div class="flex-i red"></div>
        <div class="flex-i blue"></div>
        <div class="flex-i green"></div>
        <div class="flex-i red"></div>
        <div class="flex-i blue"></div>
        <div class="flex-i green"></div>
        <div class="flex-i red"></div>
        <div class="flex-i blue"></div>
        <div class="flex-i green"></div>
        <div class="flex-i red"></div>
        <div class="flex-i blue"></div>
        <div class="flex-i green"></div>
        <div class="flex-i red"></div>
        <div class="flex-i blue"></div>
    </div>
</div>

CSS

.flex-c:after {
    content: '';
    display: table;
    clear: both;
}
.flex-i.red { background-color: red; }
.flex-i.blue {background-color: blue; }
.flex-i.green {background-color: green;}
.flex-i {
    transform: rotate(90deg) scaleY(-1);
    height: 100px;
    width: 100px;
    background-color: gray;
    margin: 0 10px 10px 0;
    float: left;
}
.flex-i:after,
.flex-i.big:before {
    content: '';
    height: 100px;
    width: 100px;
    left: 110px;
    top: 0;
    position: absolute;
    background-color: pink;
}

.flex-i.big:after {
    left: 220px;
}
.flex-i.big:before {
    left: 220px;
    bottom: 0;
    top: auto;
}

.big {
    width: 210px;
    height: 210px;
}

Additionally

You may be able to benefit from using a library such as Isotopes JS masonry layout

It assists you to produce a layout style that you've shown.

Here is a working example.

HTML

<div id="container">
    <div class="item"></div>
    <div class="item w2"></div>
    <div class="item"></div>
    <div class="item w2"></div>
    <div class="item h2"></div>
    <div class="item"></div>
    <div class="item h2"></div>
    <div class="item w2 h2"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item h2"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item w2"></div>
    <div class="item h2"></div>
    <div class="item"></div>
    <div class="item h2"></div>
</div>

CSS

#container {
    border: 1px solid;
    padding: 7px;
}

.item {
    width: 60px;
    height: 60px;
    float: left;
    margin: 3px;
    background: #CCC;
}

.item.w2 {
    width: 130px;
}

.item.h2 {
    height: 130px;
}

JS - note that you have to apply the masonry to the parent element, which in this case is the id of container

$( function() {
    var $container = $('#container').masonry({
        itemSelector: '.item',
        columnWidth: 70
    });
});

View the jsFiddle here

Ridgeling answered 27/4, 2018 at 22:1 Comment(5)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewBefog
@SamvelAleqsanyan a working example has been updated in this post. More options for configuration are available on the IsotopeJS link provided.Ridgeling
@Ridgeling the OP is looking for a CSS Grid solution, not a IsotopJS solutionBroadbill
@MikeDiglio a pure css solution has been added along with the isotopeJS solution. IsotopeJS was suggested as it is a library that specifically handles this functionality for developers.Ridgeling
@SamvelAleqsanyan i will jump into answering questions vs providing answers that don't require clarification from the asker as I have ample experience in the field of js/html/css/jquery. Feel free to read up on the documentation on the Isotope.js library as it provides a solution to this specific question with a javascript library. Otherwise I have provided a pure css solution if the library not able to be used in the application.Ridgeling
O
0

So since you specifically wanted to achieve this using CSS grid, this isn't exactly what you wanted, but perhaps it will do:

you can drop the DIVS entirely, use the images directly and set the row height by setting height: 350px; within .cell class (that is moved to apply on the images).

In addition, the .galary will be a flex, with flex-wrap enabled so that every item that overflows will start a new line.

And last, add flex-grow:1; to .cell (the img tags) so they will take up any empty space in their line.

* In the snippet, I've also added object-fit: cover; to the images, but this will hide any overflowing part of the image, so you play with it and see what fits for you

#gallery {
  background: #cfc;
  padding: 32px;
  display: grid;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.cell {
  background: #fcc;
  flex-grow: 1;
  object-fit: cover;
}
<div id="gallery">
    <img class="cell" src="http://via.placeholder.com/350x500" />
    <img class="cell" src="http://via.placeholder.com/250x150" />
    <img class="cell" src="http://via.placeholder.com/150x150" />
    <img class="cell" src="http://via.placeholder.com/370x150" />
</div>
Ohaus answered 4/1, 2023 at 20:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.