CSS-сетка: контент для использования свободного места, но прокручивается, когда больше

Я впервые работал с CSS Grid Layouts, и они потрясающие. Однако сейчас у меня возникают проблемы с управлением одной из моих ячеек сетки.

Я хочу, чтобы элемент, который занимает существующее свободное пространство и не более, прокручивается, когда контент становится слишком большим. Я понимаю, что размер сетки 1fr занимает единое количество доступного пространства после вычисления всего остального. Я пробовал различные размеры, такие как minmax(auto, 1fr), но безрезультатно - 1fr, кажется, расширяется, чтобы соответствовать содержимому, которое не то, что я хочу. Установка максимального размера размера, такого как 100px, также не подходит, потому что я хочу, чтобы размер определялся другими элементами в сетке.

Вот пример:

.container {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 1fr 1fr;
}

.container>div {
  border: 1px solid blue;
  border-radius: 5px;
}

.left {
  grid-column: 1;
  grid-row: 1/4;
}

.header {
  grid-column: 2;
  grid-row: 1;
}

.problem-child {
  grid-column: 2;
  grid-row: 2;
  overflow-y: scroll;
}

.footer {
  grid-column: 2;
  grid-row: 3;
}
<div class="container">
  <div class="left">left<br>I don't want this one to scroll<br>this should<br>determine<br>the height of the whole grid container</div>
  <div class="header">column header</div>
  <div class="problem-child">problem child:<br>I<br>want<br>this<br>to<br>scroll<br>rather<br>than<br>making<br>everything<br>tall</div>
  <div class="footer">column footer</div>
</div>

Ответ 1

Вы можете использовать max-height:100%;, а также min-height, чтобы оставить достаточную высоту, чтобы показать правильную полосу прокрутки. (firefox сделает, хром в это время не будет)

.container {
  display: grid;
  grid-template-rows: auto minmax(1fr, 25vh) auto;
  grid-template-columns: 1fr 1fr;
}

.container>div {
  border: 1px solid blue;
  border-radius: 5px;
}

.left {
  grid-column: 1;
  grid-row: 1/4;
}

.header {
  grid-column: 2;
  grid-row: 1;
}

.problem-child {
  grid-column: 2;
  grid-row: 2;
  min-height:4em;
  max-height:100%;
  overflow-y: auto;
}

.footer {
  grid-column: 2;
  grid-row: 3;
}
<div class="container">
  <div class="left">left<br>I don't want this one to scroll<br>this should<br>determine<br>the height of the whole grid container</div>
  <div class="header">column header</div>
  <div class="problem-child">problem child:<br>I<br>want<br>this<br>to<br>scroll<br>rather<br>than<br>making<br>everything<br>tall</div>
  <div class="footer">column footer</div>
</div>

Ответ 2

Добавление поверх решения @G-Cyr. Для работы max-height должен быть по крайней мере один элемент, абсолютно позиционированный для max-height. Установите контейнер, который будет полностью расположен.

.container {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 1fr 1fr;
  height: 100%;
  width: 100%;
  position: absolute;
}

.container>div {
  border: 1px solid blue;
  border-radius: 5px;
}

.left {
  grid-column: 1;
  grid-row: 1/4;
}

.header {
  grid-column: 2;
  grid-row: 1;
}

.problem-child {
  grid-column: 2;
  grid-row: 2;
  max-height: 100%;
  overflow-y: auto;
}

.footer {
  grid-column: 2;
  grid-row: 3;
}
<div class="container">
  <div class="left">left<br>I don't want this one to scroll<br>this should<br>determine<br>the height of the whole grid container</div>
  <div class="header">column header</div>
  <div class="problem-child">problem child:<br>I<br>want<br>this<br>to<br>scroll<br>rather<br>than<br>making<br>everything<br>tall</div>
  <div class="footer">column footer</div>
</div>

Ответ 3

Существует более элегантное решение, в котором используются единицы высоты окна просмотра (vh). Просто примените 100vh к вашему контейнеру:

.container {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 1fr 1fr;
  height: 100vh; /* <- does the trick */
}

.container>div {
  border: 1px solid blue;
  border-radius: 5px;
}

.left {
  grid-column: 1;
  grid-row: 1/4;
}

.header {
  grid-column: 2;
  grid-row: 1;
}

.problem-child {
  grid-column: 2;
  grid-row: 2;
  overflow-y: scroll;
}

.footer {
  grid-column: 2;
  grid-row: 3;
}

body {
  margin: 0; /* fixes stackoverflow markup */
}
<div class="container">
  <div class="left">left<br>I don't want this one to scroll<br>this should<br>determine<br>the height of the whole grid container</div>
  <div class="header">column header</div>
  <div class="problem-child">problem child:<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tristique felis eros, et luctus turpis pellentesque nec. Nunc gravida est quis vestibulum tristique. Maecenas consectetur cursus pulvinar. Aenean quis diam sollicitudin nisi ullamcorper consectetur. Nullam dapibus eleifend sollicitudin. Donec ut pulvinar erat, quis suscipit urna. Donec at turpis nunc. Sed diam lectus, tincidunt vel tellus eu, consectetur rhoncus urna. Fusce tempus lectus tellus, sagittis laoreet arcu sagittis vitae. Phasellus varius orci accumsan orci vulputate semper. Maecenas mauris tortor, congue sit amet volutpat pretium, tincidunt et ligula. Donec convallis bibendum nunc at gravida. Pellentesque suscipit, nisl nec commodo tincidunt, metus nibh posuere diam, et finibus nulla mauris scelerisque sem. Maecenas fringilla ullamcorper consectetur.

Nullam non purus vitae nisl scelerisque molestie at et nibh. In hac habitasse platea dictumst. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vestibulum bibendum mattis dignissim. Praesent rutrum ultrices mauris, in maximus orci suscipit iaculis. Ut non neque feugiat, vestibulum massa sed, malesuada nulla. Phasellus eu vehicula odio. Proin vulputate, purus ac posuere pharetra, velit ipsum sollicitudin tellus, ut fermentum sapien risus eu lorem. Nullam viverra mollis finibus. Curabitur cursus lobortis dapibus. Cras aliquet dignissim diam, eu consectetur risus pretium a.

Phasellus consectetur vel tellus et dignissim. Quisque sit amet porta sem, et sagittis sem. Vestibulum blandit tellus enim, sed convallis lectus semper eget. Nunc varius dignissim nunc. Ut ac fringilla justo. Aenean non ex lacus. Mauris pretium egestas facilisis.

Fusce imperdiet turpis vitae tortor tristique, vitae pulvinar erat cursus. Aliquam blandit justo rutrum, efficitur leo vitae, fringilla enim. Cras facilisis dapibus mattis. Duis quis accumsan ipsum. Curabitur consectetur nisi vel mauris tincidunt, sed finibus nisi faucibus. Curabitur efficitur nulla at turpis vehicula congue. Aenean quis nulla id massa elementum commodo quis ut risus. Aliquam congue metus vitae mi dictum aliquet. Nulla facilisi. Donec auctor nisl non turpis scelerisque, ut vestibulum mauris malesuada. Mauris vulputate ut mi vitae congue. Nam ac nulla in neque semper laoreet at in metus.

Cras bibendum, magna ut convallis consectetur, lacus nunc luctus metus, a faucibus quam leo et dui. Nam non sagittis lacus. In leo dui, euismod a tellus eu, volutpat cursus libero. Praesent suscipit mollis turpis, eu imperdiet lorem imperdiet in. Suspendisse potenti. Ut bibendum semper ante, at blandit enim feugiat ut. Nullam eu vehicula lorem. Curabitur maximus ipsum ex, eget mattis urna consectetur id.</div>
  <div class="footer">column footer</div>
</div>

Ответ 4

Если вы определяете другую сетку внутри problem-child, то она снова отображается неправильно. Вы должны overflow: auto атрибут overflow: auto с любой родительской сетки на дочерние. Проверьте данный кодекс:

body {
  height: 100vh;  
  display: grid;
  grid-template-rows: 30px 1fr 20px;
  margin: 0;
}
.header {
  background: green;
}
.footer {
  background: magenta;
}
.page {
  overflow: auto;
}
.container{
  height: 100%;
  display: grid;
  grid-template-rows: 30px 1fr 1fr 30px;
}

.fill-content {
  background: red;
  overflow: auto;
}

.fix-content {
  background: yellow;  
}

.large {
  background: blue;
  width: 100%;
  height: 150px;
}
<div class="header">Page HEader
</div>
<div class="page"> 
<div class="container">
  <div class="fix-content"></div>
  <div class="fill-content">
    <div class="large">fill content 1 by vertical space or scroll it (red layer is filled, blue makes it scrolling)</div>
  </div>
  <div class="fill-content">
    <div class="large">fill content 2 by vertical space or scroll it (red layer is filled, blue makes it scrolling)</div>
  </div>
  <div class="fix-content"></div>
</div>
</div>
<div class="footer">Page Footer</div>