CSS Grid: wrapping with multiple sizes of columns

Viewed 1204

Here is my issue.

I've this basic layout based on CSS grid:

.title {
  font-weight: bold;
}

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-gap: 1rem;
}

.grid > * {
  border: 1px solid red;
}
<div class="grid">
  <div class="title">Title 1</div><div>My Panel for Title 1</div>
  <div class="title">Title 2</div><div>My Panel for Title 2</div>
</div>

As you can see, by default, I've 1 quarter for the first col, 3 quarters for the second one.

In this example, the second column is not so filled, but in the real case, i've got a whole panel with a lot of stuff inside.

I'd like that before squeezing a lot the big column, it squeezes the first one (which is always short, being just the title of the category) but when the first column is squeezed to its min size, the whole grid wraps so the title gets above each cell instead of being on its left.

So basically summed up:

  • If I have tons of space, i want 1/4 3/4 layout.
  • If the page is squeezed, i want the first column to be shrinked first.
  • If the first column cannot be shrinked anymore (min-content is reached), then it wraps.

For the wrapping, i've a read a lot about repeat and auto-fit, but since it only takes one size configuration, i didn't figure out how to manage the 1fr/3fr case.

Do you have an idea about how i can handle this? Is it even feasible?

Thank you by advance!

3 Answers

Use repeat for the grid. for the 3fr wide item use grid-column: span 3;

You're trying to use the CSS Grid sledgehammer to pound a tiny nail. As @TemaniAfif said Flexbox would be a better solution. But if you want column widths to be locked across rows that's more difficult with Flexbox.

Alternately, there's a thing called table that's been in the HTML & CSS specs for pretty much ever... It's really best used for grids of data not layout but based on your example and needs it might be perfect.

Just because tables haven't been "cool" for years, doesn't mean there aren't still legitimate uses for them.

You need an internal flexbox for that.

https://codepen.io/rei-of-mf-sunshine/pen/GRmJMpL

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 100px 500px 50px;
  gap: 0px 0px;
}

.logo { grid-area: 1 / 1 / 2 / 2; }

.metadata { grid-area: 1 / 2 / 2 / 4; }

.body {
  grid-area: 2 / 1 / 3 / 4;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-content: stretch;
  align-items: flex-start;
  gap: 5mm;
  div {
    flex: 0 1 auto;
    max-width: 50%;
  }
}

.footer {
  order: 0;
  flex: 0 1 auto;
  align-self: auto;
}


html, body , .container {
  height: 100%;
  margin: 0;
}

The downside is you need a fixed height on the parent of the flexbox. When that height is exceeded there will be a hard break, kind of like another sheet of paper.

Related