Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

grid-gap only updates the width of one side

Tags:

css

css-grid

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>
like image 364
David Avatar asked Jun 26 '26 02:06

David


2 Answers

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>
like image 100
m4n0 Avatar answered Jun 29 '26 03:06

m4n0


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.

like image 29
Temani Afif Avatar answered Jun 29 '26 03:06

Temani Afif