70

I have a card built with CSS Grid layout. There might be an image to the left, some text to the right top and maybe a button or a link at the right bottom.

In the code below, how can I make the green area take up as much space as possible and at the same time make the blue area take up as little space as possible?

The green should push the blue area down as far as possible.

https://jsfiddle.net/9nxpvs5m/

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas:
    "one two"
    "one three"
}

.one {
  background: red;
  grid-area: one;
  padding: 50px 0;
}

.two {
  background: green;
  grid-area: two;
}

.three {
  background: blue;
  grid-area: three;
}
<div class="grid">
  <div class="one">
    One
  </div>
  <div class="two">
    Two
  </div>
  <div class="three">
    Three
  </div>
</div>
TylerH
  • 20,799
  • 66
  • 75
  • 101
Jens Törnell
  • 23,180
  • 45
  • 124
  • 206
  • Not an answer to the question as-is, but might still be of value: I'd do it with flexbox and an additional container around `.two` and `.three`: https://jsfiddle.net/9nxpvs5m/2/ – domsson Aug 21 '17 at 14:52
  • your actual question doesn't seem to match the title. the title suggests trying to take up the remaining space, but the actual question talks about taking up as much or as little space as possible. – Michael Jul 15 '22 at 19:56

6 Answers6

84

Adding grid-template-rows: 1fr min-content; to your .grid will get you exactly what you're after :).

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-rows: 1fr min-content;
  grid-template-areas:
    "one two"
    "one three"
}

.one {
  background: red;
  grid-area: one;
  padding: 50px 0;
}

.two {
  background: green;
  grid-area: two;
}

.three {
  background: blue;
  grid-area: three;
}
<div class="grid">
  <div class="one">
    One
  </div>
  <div class="two">
    Two
  </div>
  <div class="three">
    Three
  </div>
</div>

Jens edits: For better browser support this can be used instead: grid-template-rows: 1fr auto;, at least in this exact case.

Jens Törnell
  • 23,180
  • 45
  • 124
  • 206
Kevin Powell
  • 1,009
  • 7
  • 7
  • 1
    I had a similar problem with a single-column, four-row grid. Used `grid-template-rows: auto auto auto 1fr;` and it now expands the final row to fill the remainder of the page. This is my goal — thanks for the tip. – scottperezfox Sep 22 '21 at 00:39
2

A grid is a series of intersecting rows and columns.

You want the two items in the second column to automatically adjust their row height based on their content height.

That's not how a grid works. Such changes to the row height in the second column would also affect the first column.

If you must use CSS Grid, then what I would do is give the container, let's say, 12 rows, then have items span rows as necessary.

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-rows: repeat(12, 15px);
}

.one {
  grid-row: 1 / -1;
  background: red;
}

.two {
  grid-row: span 10;
  background: lightgreen;
}

.three {
  grid-row: span 2;
  background: aqua;
}

.grid > div {
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="grid">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
</div>

Otherwise, you can try a flexbox solution.

.grid {
  display: flex;
  flex-flow: column wrap;
  height: 200px;
}

.one {
  flex: 0 0 100%;
  width: 30%;
  background: red;
}

.two {
  flex: 1 0 1px;
  width: 70%;
  background: lightgreen;
}

.three {
  background: aqua;
}

.grid>div {
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="grid">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • I had considered the *min-content* approach, but that value has weak browser support. It didn't work in Safari and Firefox when I tested it. – Michael Benjamin Aug 28 '17 at 10:53
1

A possible approach might be grouping two and three together, and using flexbox:

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas: "one two"
}

.one {
  background: red;
  grid-area: one;
  padding: 50px 0;
}

.wrap {
  grid-area: two;
  display: flex;
  flex-direction: column;
}

.two {
  background: green;
  flex: 1;
}

.three {
  background: blue;
}
<div class="grid">
  <div class="one">
    One
  </div>
  <div class="wrap">

    <div class="two">
      Two
    </div>
    <div class="three">
      Three
    </div>
  </div>
</div>
EvilDr
  • 8,943
  • 14
  • 73
  • 133
sol
  • 22,311
  • 6
  • 42
  • 59
  • Exactly my line of thought. Flexbox is really my go-to solution these days. However, it is a pitty *flex*box isn't actually *flex*ible enough to get this simple layout going without an additional container around `.two` and `.three` - or is there a way? – domsson Aug 21 '17 at 14:54
  • @domsson Not that I can think of :) – sol Aug 21 '17 at 14:55
  • 1
    I think this is a workaround so I'll wait a while before accepting this as an answer. A grid only solution if exists will be accepted as an answer. – Jens Törnell Aug 21 '17 at 15:00
1

When using grid, and you have grid template area used, and by chance you gave a particular area a width, you are left with a space grid does automatically. In this situation, let grid-template-columns be either min-content or max-content, so that it adjusts its position automatically.

0

Definitely not the most elegant solution and probably not best practice, but you could always add more lines of

"one two"

before the part where you have

"one three"

so it ends up looking like

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas:
    "one two"
    "one two"
    "one two"
    "one three"
}

Again, pretty sure this is just a work around and there's better solutions out there... But this does work, to be fair.

gymnast66x
  • 25
  • 1
  • 3
-6

Just use width: 100% and height: 100% in the CSS class of the item you want to fill the grid. Join a max-width property and a max-height property if you don't want a grid item inside a grid container to grow more than some size.

fcdt
  • 2,371
  • 5
  • 14
  • 26