Строки сетки, созданные с помощью grid-auto-rows, не растягивают родительский стек

#html #css #css-grid

#HTML #css #css-grid

Вопрос:

Я пытаюсь создать гибкий макет, который растягивается для добавления дополнительного контента.

 .parent {
  min-height: 500px;
  border: 1px solid;
  display: grid;
  grid-template-rows: 100px 1fr;
}

.child {
  display: grid;
  grid-auto-rows: 100%;
  border: 1px solid;
}


.header {
  background: yellow;
}

.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  

Я хочу избежать явного указания высоты каждого элемента содержимого. Если я использую grid-auto-rows: 400px , это создает строку высотой 400 пикселей для каждого раздела содержимого, а родительский раздел растягивается, чтобы вместить все разделы содержимого. Как и должно быть.

Но если я использую grid-auto-rows: 100% , это создает строки с высотой, равной 100% высоты дочернего элемента каждая, в то время как родительский не растягивается.

Есть ли способ избежать этого и заставить родительский стек увеличиваться, чтобы вместить все содержимое внутри, без явного указания высоты каждого из дочерних элементов?

Комментарии:

1. Взгляните на developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows . Полагаю, вы ищете что-то вроде minmax или fit-content

2. На самом деле нет. Из того, что я понял, <pre>minmax</pre> и <pre>fit-content</pre> позволяют элементу занимать пространство между размерами to или до некоторого размера. В то время как я хочу сделать дочерний элемент высотой, равной части начальной высоты родительского элемента, а затем увеличить, также увеличив родительский элемент. Поэтому, если дочерний элемент растет (добавляется больше содержимого), то родительский элемент также растет. Но начальный размер дочернего элемента (и пространство для каждой части содержимого) задается его родительским элементом.

Ответ №1:

Но если я использую grid-auto-rows: 100%, это создает строки высотой, равной 100% высоты дочернего элемента каждая, в то время как родительский элемент не растягивается.

Это сложнее, чем это. Настройка 100% означает, что строка будет составлять 100% от child высоты, которая определена как 1fr внутри родительского элемента, таким образом, это 400px . Таким образом, высота каждой строки должна быть 400px , и наличие более одной строки создаст переполнение, поскольку высота child также 400px равна.

Другими словами, вы определили размер одной строки, равный высоте вашего элемента, таким образом, более чем одна строка наверняка создаст переполнение.

Одна из идей исправления состоит в том, чтобы рассмотреть, 1fr внутри grid-auto-rows которого все content будут иметь одинаковую высоту, и если один из них будет расти, все будут расти одинаково, растягивая элемент child and parent .

Установка высоты для одного из них:

 .parent {
  min-height: 500px;
  border: 1px solid;
  display: grid;
  grid-template-rows: 100px 1fr;
}

.child {
  display: grid;
  grid-auto-rows: 1fr;
  border: 1px solid;
}


.header {
  background: yellow;
}

.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}

.content:nth-child(2) {
  height:300px;
  background:red;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  

Добавление содержимого:

 .parent {
  min-height: 500px;
  border: 1px solid;
  display: grid;
  grid-template-rows: 100px 1fr;
}

.child {
  display: grid;
  grid-auto-rows: 1fr;
  border: 1px solid;
}


.header {
  background: yellow;
}

.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content">
    lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>lorem ipsum<br>
    </div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  

Вы также можете установить min-height для любого дочернего элемента, чтобы создать нижнюю границу:

 .parent {
  min-height: 500px;
  border: 1px solid;
  display: grid;
  grid-template-rows: 100px 1fr;
}

.child {
  display: grid;
  grid-auto-rows: 1fr;
  border: 1px solid;
}


.header {
  background: yellow;
}

.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}
.content:last-child {
  min-height:300px;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  

Увеличение родительской высоты также приведет к расширению содержимого:

 .parent {
  min-height: 900px;
  border: 1px solid;
  display: grid;
  grid-template-rows: 100px 1fr;
}

.child {
  display: grid;
  grid-auto-rows: 1fr;
  border: 1px solid;
}


.header {
  background: yellow;
}

.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  


Обновить

Основываясь на вашем требовании в комментариях, вот взлом, который будет делать то, что вы хотите:

 .parent {
  border: 2px solid red;
  display: grid;
  grid-template-rows: 100px;
  grid-auto-rows: 300px; /*this will define the child height*/
}

.child {
  display: grid;
  border: 1px solid;
  display:contents; /*use this to cross the child and make content grid element*/
}


.header {
  background: yellow;
}

.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  

Я использовал display:contents для создания дочерней части сетки, затем я явно определил высоту каждого из них внутри родительского, а не min-height

Комментарии:

1. Моей мыслью было создать независимый дочерний элемент, который содержит некоторое содержимое равного размера. Когда добавляется больше содержимого, дочерний становится больше, добавляя новые строки. В то время как родительский задает объем пространства, который будет занимать дочерний. Таким образом, если минимальная высота родительского элемента равна 500 пикселям, 100 пикселям для заголовка и 400 для дочернего элемента, дочерний элемент должен быть равен 400 пикселям для каждого фрагмента содержимого. 2 фрагмента содержимого — заголовок размером 100 пикселей, дочерний размер 800 пикселей и родительский размер 900 пикселей. Но, похоже, это слишком большая ответственность для родительского элемента. Спасибо за ответ!

2. @BlackDrake дело не в ответственности , но вы мыслите циклически. Если вы снова прочтете свой комментарий, вы заметите, что вы сказали, что родитель определит, затем дочерний будет расширяться -> оба не могут работать, потому что у вас будет цикл (как описано в моем ответе). Либо родительский стек определит что-то, что будет использовано позже, либо дочерний стек определит родительскую высоту на основе их содержимого. Наличие обоих с использованием этой конфигурации почему-то невозможно.

3. @BlackDrake проверьте обновление, я добавил решение, близкое к тому, что вы хотите

4. Это не совсем цикл, но да, я просто надеялся, что есть способ создавать дополнительные строки на основе минимальной высоты, одновременно увеличивая текущую высоту родительского стека. Ваше решение после обновления в основном заставляет его работать, но оно работает довольно странно (почему первый раздел содержимого имеет высоту 0?) и действует так, как будто в нем нет «дочерних» элементов. Тем не менее, благодарю вас за ответ. Это действительно помогло мне понять, что происходит и как найти решение.

5. @BlackDrake забыл удалить 1fr (проблема с первым содержимым), исправлено. И да, это действует так, как будто нет дочернего элемента, который является целью display:contents . Идея состоит в том, чтобы сохранить html, но имитировать все содержимое как часть сетки, чтобы на них могла повлиять высота, определенная в родительском ( caniuse.com/#feat=css-display-contents )

Ответ №2:

Установка значения 100% для внутренней сетки приведет к тому, что она займет все пространство в элементе внешней сетки и вызовет переполнение. Вы должны установить для него явность в 400 пикселей (в этом случае элемент внешней сетки будет расширяться)

Вы можете установить grid-template-rows: 100px minmax(400px, 1fr) вместо настройки min-height для внешней сетки и grid-auto-rows: 400px для внутренней сетки. Чтобы упростить его, вы можете использовать CSS variables :

 :root {
  --h: 400px;
}
.parent {
  border: 1px solid;
  display: grid;
  grid-template-rows: 100px minmax(var(--h), 1fr);
}
.child {
  display: grid;
  grid-auto-rows: var(--h);
  border: 1px solid;
}
.header {
  background: yellow;
}
.content {
  background: rgba(255, 0, 0, 0.3);
  border: 1px dashed blue;
}  
 <div class="parent">
<div class="header"></div>
  <div class="child">
    <div class="content"></div>
    <div class="content"></div>
    <div class="content"></div>
  </div>
</div>  

Комментарии:

1. установка minmax, вероятно, бесполезна в этом случае, потому что fr всегда будет выигрывать, поскольку по крайней мере одно содержимое будет иметь размер 400 пикселей, поэтому во всех случаях оно будет >= 400 пикселей.

2. это не бесполезно, см. min-height не хранится в parent … проверьте высоту content в приведенном выше фрагменте — она равна 400 пикселей … и вся настройка работает в соответствии с требованиями OP, так что это не должно быть проблемой 🙂

3. Я имел в виду, что если вы замените minmax на only 1fr , вы также получите тот же результат, потому что ваш контент имеет размер 400 пикселей

4. grid-template-rows: 100px minmax(400px, 1fr) гарантирует, что, даже если внутренняя сетка изменится, вторая строка внешней сетки будет иметь размер не менее 400 пикселей … вот почему 🙂

5. Спасибо. Моей целью было предотвратить дочерний элемент в зависимости от размера родительского элемента. Поэтому, если я сделаю высоту родительского элемента 800 пикселей, дочерний элемент будет скорректирован. Для меня действительно непонятно, почему 100% вызывает переполнение, в то время как пиксели работают нормально.