Home > Net >  Why is the row height different when using grid-template-areas with 2 rows vs 4?
Why is the row height different when using grid-template-areas with 2 rows vs 4?

Time:09-26

I'm getting a surprising behavior using grid-template-areas that I don't understand. You can see in the following CodePen a layout using 4 rows:

A 4 row layout using grid-template-areas.

HTML:

<div >
  <h3>Title</h3>
  <div >Item 1</div>
  <div >Item 2</div>
  <div >Item 3</div>
  <p >Paragraph</p>
</div>

CSS:

.container {
  display: grid;
  gap: 1em;
  grid-template-areas:
    'title item1'
    'description item1'
    'description item2'
    'description item3';
  grid-template-columns: 1fr 2fr;
  width: 640px;
}
h3 {
  grid-area: title;
  background-color: red;
  margin: 0;
}
.item1 {
  grid-area: item1;
}
.item2 {
  grid-area: item2;
}
.item3 {
  grid-area: item3;
}
.description {
  grid-area: description;
  background-color: yellow;
  margin: 0;
}
.item1, .item2, .item3 {
  background-color: blue;
  padding: 2em;
  height: 100px;
}

Everything works as desired, specifically the way the height of the "Title" grid cell is determined by its content.

But in this version that uses 2 rows, the height of the "Title" and "Paragraph" rows is different:

A 2 row layout using grid-template-areas.

HTML:

<div >
  <h3>Title</h3>
  <div >Item 1</div>
  <p >Paragraph</p>
</div>

CSS:

.container {
  display: grid;
  gap: 1em;
  grid-template-areas:
    'title item1'
    'description item1';
  grid-template-columns: 1fr 2fr;
  width: 640px;
}
h3 {
  grid-area: title;
  background-color: red;
  margin: 0;
}
.item1 {
  grid-area: item1;
}
.description {
  grid-area: description;
  background-color: yellow;
  margin: 0;
}
.item1 {
  background-color: blue;
  padding: 2em;
  height: 400px;
}

The "Title" grid row is now 50% of the total grid height, rather than being determined by its contents. Why does this change when using 2 rows instead of 4? How could I get the 2-row version to have the "Title" cell's height determined by its content?

Thanks for any help!

CodePudding user response:

Without going into the minutiae of the track sizing algorithm, Section 11.5 of the Grid specification says

11.5. Resolve Intrinsic Track Sizes

This step resolves intrinsic track sizing functions to absolute lengths. First it resolves those sizes based on items that are contained wholly within a single track. Then it gradually adds in the space requirements of items that span multiple tracks, evenly distributing the extra space across those tracks insofar as possible.

In the first case, the title spans only one track, so its height is set and fixed, and all the free space is allocated to the description because it spans multiple tracks.

In the second case, the title and description both span a single track, so the space is divided evenly between them.


As far as getting the 2-row version to have the "Title" cell's height determined by its content, as UmairFarooq already says. you'd need to define the heights of the two tracks. I'd go with grid-template-rows: auto 1fr;

.container {
  display: grid;
  gap: 1em;
  grid-template-areas:
    'title item1'
    'description item1';

  grid-template-columns: 1fr 2fr;
  grid-template-rows: auto 1fr;
  width: 640px;
}
h3 {
  grid-area: title;
  background-color: red;
  margin: 0;
}
.item1 {
  grid-area: item1;
}
.description {
  grid-area: description;
  background-color: yellow;
  margin: 0;
}
.item1 {
  background-color: blue;
  padding: 2em;
  height: 100px;
}
<div >
  <h3>Title</h3>
  <div >Item 1</div>
  <p >Paragraph</p>
</div>

CodePudding user response:

You have to define the row size as well..

grid-template-rows: 0.3fr 1.7fr; first row will take 0.3fr and bottom row will be 1.7fr

.container {
  display: grid; 
  grid-template-columns: 1fr 2fr; 
  grid-template-rows: 0.3fr 1.7fr; 
  gap: 10px 10px; 
  grid-template-areas: 
    "title item1"
    "description item1"; 
}

h3 {
  grid-area: title;
  background-color: red;
  margin: 0;
}

.item1 {
  grid-area: item1;
}

.description {
  grid-area: description;
  background-color: yellow;
  margin: 0;
}

.item1 {
  background-color: blue;
  padding: 2em;
  height: 400px;
}
<div >
  <h3>Title</h3>
  <div >Item 1</div>
  <p >Paragraph</p>
</div>

  • Related