Home > Enterprise >  Making a grid item span all the rows without affecting the other grid items
Making a grid item span all the rows without affecting the other grid items

Time:01-27

I'm trying to make a dynamic grid where each new item goes into a new row inside a single column, but the last item must break into a new column and fill the entire grid-column, without affecting the other rows in the first column.

Note that the amount of items is dynamic, so I cannot use any fixed values and selectors to define the layout.

The layout im looking for:

enter image description here

What I've tried

As you can see, the rows in the first column have an equal height. I want the item inside the first row of the first column to keep its height relatively to its content like the other rows in the first column.

The height of the only item in the second column is irrelevant in this case, its height value will always be higher than the height of the other items in the grid.

ul {
  margin: 0;
  list-style-type: none;
  display: grid;
  grid-auto-flow: row;
  grid-template-columns: auto auto;
  grid-gap: 20px;
  max-width: 600px;
}

li {
  grid-column-start: 1;
  border: 1px solid black;
}

li.last {
  grid-column-start: 2;
  grid-row: 1/-1;
}

img {
max-width: 100%;
}
<ul>
  <li>here's some content</li>
  <li>here's some content</li>
  <li>here's some content</li>
  <li>here's some content</li>
  <li ><img src="https://images.unsplash.com/photo-1481349518771-20055b2a7b24?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8cmFuZG9tfGVufDB8fDB8fA==&w=1000&q=80"></li>
</ul>

CodePudding user response:

I think you have the right idea in your code for the last item:

li.last {
  grid-column-start: 2;
  grid-row: 1/-1;
}

This tells the last item to span from top to bottom.

The problem is that numeric indexes (1 / -1) only work with explicit grids. In other words, grids with defined columns and rows. You're using an implicit grid, where columns and rows are automatically generated, as needed.

Considering your requirements ("cannot use any fixed values and selectors to define the layout") this method won't work.

You could try flex, but even then, a height would have to be defined. Here's the concept:

ul {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  gap: 20px;
  max-width: 600px;
  margin: 0;
  list-style-type: none;
  padding: 0;
  height: 80vh;
}

li {
  flex: 1;
  border: 1px solid black;
}

li.last {
  flex-shrink: 0;
  height: 100%;
}

img {
  width: auto;
  height: 100%;
}
<ul>
  <li>here's some content</li>
  <li>here's some content</li>
  <li>here's some content</li>
  <li>here's some content</li>
  <li ><img src="https://images.unsplash.com/photo-1481349518771-20055b2a7b24?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8cmFuZG9tfGVufDB8fDB8fA==&w=1000&q=80"></li>
</ul>

jsFiddle demo

More info:

  • Related