David
David

Reputation: 4895

grid-gap only updates the width of one side

enter image description here

As you can see, when I change the grid-gap, only the width of 1, 3 and 4 are updated.
The width of 2 is not updated at all.
I want it to update the width of 1 and the width of 2, 3 and 4.

The demo of MDN shows that it's possible to resize all items accordingly.
https://developer.mozilla.org/en-US/docs/Web/CSS/gap

Here's my code

.container {
  display: grid;
  width: 500px;
  height: 100px;
  gap: 20px;    /* Try to change this, width of 2 isn't updated */
  grid-template-columns: 2fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  transition: gap 0.3s linear;
}

.child {
  background-color: gray;
  text-align: center;
  font-size: 50px;
  color: white;
  line-height: 70px
}

.child-1 {
  grid-row-start: 1;
  grid-row-end: 3;
}


.child-2 {
  grid-column-start: 2;
  grid-column-end: 4;
}
<div class="container">
  <div class="child child-1">1</div>
  <div class="child child-2">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>

Upvotes: 3

Views: 810

Answers (2)

m4n0
m4n0

Reputation: 32255

Problem:

It's not easy to see it from outside but if you can Examine the Grid Layout in Firefox developer tools you can see the difference.

Examining the current Grid

You can notice that the width of the two columns of 2 is changing yet the parent remains constant because it is spanning them both and breaking it would make the grid asymmetrical.


Solution:

You can use this Grid Generator and create some changes to the code for the following setup:

2fr + 1fr + 1fr + 1fr + 1fr

Now 1 spans two fractions of the layout, 2 spans four fractions while 3 and 4 spans two fractions each. In this way, the whole structure is symmetrical.

.container {
  display: grid;
  width: 500px;
  height: 100px;
  grid-gap: 20px; /* Try to change this, width of 2 isn't updated */
  grid-template-columns: 4fr 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  transition: grid-gap 1s ease-in-out;
}

.container:hover {
  grid-gap: 0px;
}

.child {
  background-color: gray;
  text-align: center;
  font-size: 50px;
  color: white;
  line-height: 70px;
}

.child-1 {
  grid-area: 1 / 1 / 3 / 2;
}

.child-2 {
  grid-area: 1 / 2 / 2 / 6;
}

.child-3 {
  grid-area: 2 / 2 / 3 / 4;
}

.child-4 {
  grid-area: 2 / 4 / 3 / 6;
}
<div class="container">
  <div class="child child-1">1</div>
  <div class="child child-2">2</div>
  <div class="child child-3">3</div>
  <div class="child child-4">4</div>
</div>

Upvotes: 4

Temani Afif
Temani Afif

Reputation: 272744

It's because the width of (2) include a gap so its width is 2fr + gap. changing the gap will also change the fr and the width will remain constant.

in this case 1fr = (500px - 2*gap)/4 so 2fr + gap = (500px - 2*gap)/2 + gap = 250px

Change the code and use a different structure where the width of (2) isn't constant:

.container {
  display: grid;
  width: 500px;
  height: 100px;
  grid-gap: 20px; 
  grid-template-columns: 4fr 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  animation: change 1s linear infinite alternate;
}

.child {
  background-color: gray;
  text-align: center;
  font-size: 50px;
  color: white;
  line-height: 70px;
  grid-column:span 2;
}

.child-1 {
  grid-row-start: 1;
  grid-row-end: 3;
  grid-column:span 1;
}


.child-2 {
  grid-column-start: 2;
  grid-column-end: 6;
}

@keyframes change {
   to {
     grid-gap:1px;
   }
}
<div class="container">
  <div class="child child-1">1</div>
  <div class="child child-2">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>

In this case 1fr = (500px - 4*gap )/8 and the width of (2) is 4fr + 3*gap = (500px - 4*gap)/2 + 3*gap = 250px + gap But now the (3) and (4) will be constant because 2fr + gap=(500px - 4*gap)/4 + gap = 125px

Another structure where all will update:

.container {
  display: grid;
  width: 500px;
  height: 100px;
  grid-gap: 30px; 
  grid-template-columns: 6fr 1fr 1fr 1fr 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  animation: change 1s linear infinite alternate;
}

.child {
  background-color: gray;
  text-align: center;
  font-size: 50px;
  color: white;
  line-height: 70px;
  grid-column:span 3;
}

.child-1 {
  grid-row-start: 1;
  grid-row-end: 3;
  grid-column:span 1;
}


.child-2 {
  grid-column-start: 2;
  grid-column-end: 8;
}

@keyframes change {
   to {
     grid-gap:1px;
   }
}
<div class="container">
  <div class="child child-1">1</div>
  <div class="child child-2">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>

The (2) will have a width equal to 250px + 2*gap. (3) and (4) will have a width equal to 125px + 0.5*gap

Another configuration:

.container {
  display: grid;
  width: 500px;
  height: 100px;
  grid-gap: 30px; 
  grid-template-columns: 2fr 4fr 2fr 1fr 1fr 2fr;
  grid-template-rows: 1fr 1fr;
  animation: change 1s linear infinite alternate;
}

.child {
  background-color: gray;
  text-align: center;
  font-size: 50px;
  color: white;
  line-height: 70px;
  grid-column:span 2;
}

.child-1 {
  grid-row-start: 1;
  grid-row-end: 3;
}


.child-2 {
  grid-column-start: 3;
  grid-column-end: 7;
}

@keyframes change {
   to {
     grid-gap:1px;
   }
}
<div class="container">
  <div class="child child-1">1</div>
  <div class="child child-2">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>

Basically the trick is to avoid having a constant width for your elements.

Upvotes: 4

Related Questions