Почему сетка-зазор вызывает переполнение?

Почему у меня есть переполнение по оси X в следующем фрагменте?

Переполнение генерируется, когда я применяю grid-gap: 10px к своему контейнеру сетки .body.

div:not(.header):not(.body):not(.row) {
  border: 1px solid grey;
}

.header {
  margin-top: 20px;
  display: grid;
  grid-gap: 10px;
  grid-template-areas: "header-left header-right-up" "header-left header-right-down";
  grid-template-rows: 40px 40px;
  grid-template-columns: minmax(50px, 200px) auto;
}

.header-left {
  grid-area: header-left;
}

.header-right-up {
  grid-area: header-right-up;
}

.header-right-down {
  grid-area: header-right-down;
}

.body {
  margin-top: 20px;
  display: grid;
  grid-template-columns: 25% 50% 25%;
  grid-auto-rows: 80px; 
  grid-gap: 10px;
}

.row-left {
}

.row-center {
}

.row-right {
}
<div class="header">
  <div class="header-left">image</div>
  <div class="header-right-up">content</div>
  <div class="header-right-down">long content</div>
</div>

<div class="body">
    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>

    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>

    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>
  </div>
</div>

Ответ 1

У вас есть контейнер из трех столбцов (.body):

grid-template-columns: 25% 50% 25%

Общая ширина этих столбцов составляет 100%.

Затем вы добавляете желоба между столбцами (и строками):

grid-gap: 10px

это сокращение от:

grid-column-gap: 10px;
grid-row-gap: 10px;

Итак, когда вы сложите все ширины, вы получите:

25% + 50% + 25% + 10px + 10px

Положите вкратце:

100% + 20px > 100%, which results in an overflow condition

(Примечание: свойства grid-*-gap применяются только между элементами сетки - никогда между элементами и контейнером. Поэтому мы рассчитываем два разрыва сетки, а не четыре.)

В качестве решения вместо процентных единиц попробуйте использовать единицы измерения fr, которые применяются только к свободному пространству. Это означает, что длины fr рассчитываются после применения любых длин grid-gap.

grid-template-columns: 1fr 2fr 1fr

div:not(.header):not(.body):not(.row) {
  border: 1px solid grey;
}

.header {
  margin-top: 20px;
  display: grid;
  grid-gap: 10px;
  grid-template-areas: "header-left header-right-up" "header-left header-right-down";
  grid-template-rows: 40px 40px;
  grid-template-columns: minmax(50px, 200px) auto;
}

.header-left {
  grid-area: header-left;
}

.header-right-up {
  grid-area: header-right-up;
}

.header-right-down {
  grid-area: header-right-down;
}

.body {
  margin-top: 20px;
  display: grid;
  grid-template-columns: 1fr 2fr 1fr; /* ADJUSTMENT */
  grid-auto-rows: 80px;
  grid-gap: 10px;
}

.row-left {}

.row-center {}

.row-right {}
<div class="header">
  <div class="header-left">image</div>
  <div class="header-right-up">content</div>
  <div class="header-right-down">long content</div>
</div>

<div class="body">
  <div class="row-left"></div>
  <div class="row-center"></div>
  <div class="row-right"></div>

  <div class="row-left"></div>
  <div class="row-center"></div>
  <div class="row-right"></div>

  <div class="row-left"></div>
  <div class="row-center"></div>
  <div class="row-right"></div>
</div>

Ответ 2

Если вы хотите использовать проценты или какой-то другой блок, есть еще одно решение. Использование функции minmax() позволит столбцам сжиматься до размеров родительского контейнера и не вызывать переполнение.

Решение будет выглядеть так:

grid-template-columns: minmax(auto, 25%) minmax(auto, 50%) minmax(auto, 25%);
gap: 10px;

Подробнее о функции minmax() здесь.