Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS grid: content to use free space but scroll when bigger

I've been working with CSS Grid Layouts for the first time and they're awesome. Right now, however, I'm having trouble keeping one of my grid cells under control.

What I want is to have an element that takes up the existing free space and no more, scrolling when the content gets too big. My understanding is that a grid size of 1fr takes up a uniform amount of the available space after everything else is calculated. I've tried various sizes such as minmax(auto, 1fr) but to no avail - 1fr seems to expand to fit the content which is not what I want. Setting a maximum size size like 100px is also no good because I want the size to be determined by other elements in the grid.

Here's the example:

.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>

What grid declaration (if any) can I use to let the "problem child" scroll on overflow rather than expanding?

like image 903
waterproof Avatar asked Apr 11 '17 17:04

waterproof


People also ask

How do you stop the grid overflowing?

Solution, set an explicit minimum not to auto To avoid the minimum width/height calculation size, you should therefore set the minimum width or heigth to another value than auto . And as you can see: the first column does not overflow anymore. the two columns share 50% of the space as specified in the fraction.

How do I make my grid gap responsive?

It helped me to find the following solution: Instead of setting grid-gap, set grid-column-gap and grid-row-gap separately, with grid-row-gap equal to grid-column-gap / (1 - grid-column-gap). Set padding-bottom of the container equal to grid-column-gap.

What is 1fr in CSS?

With CSS Grid Layout, we get a new flexible unit: the Fr unit. Fr is a fractional unit and 1fr is for 1 part of the available space. The following are a few examples of the fr unit at work.


3 Answers

You can use max-height:100%; and also min-height to leave enough heights to show a proper scrollbar.(firefox will do, chrome will not at this time)

.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>

As a work around, you can also use an extra wrapper in absolute position to take it off the flow and size it to the row's height: (both cases require a min-height to show properly the scrollbar when needed)

.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;    position:relative;    min-height:4em;    }    .problem-child >div {    position:absolute;    top:0;    left:0;    right:0;    max-height:100%;    overflow: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">      <div>problem child:<br>I<br>want<br>this<br>to<br>scroll<br>rather<br>than<br>making<br>everything<br>tall</div>    </div>    <div class="footer">column footer</div>  </div>
like image 58
G-Cyrillus Avatar answered Sep 23 '22 17:09

G-Cyrillus


There's a more elegant solution, which makes use of viewport height units (vh). Just apply 100vh to your container:

.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's 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>
like image 40
andr1o Avatar answered Sep 21 '22 17:09

andr1o


Adding on top of @G-Cyr's solution. There should be atleast one element absolutely positioned for max-height to work. Set container to be absolutely positioned.

.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>
like image 26
Varunkumar Nagarajan Avatar answered Sep 21 '22 17:09

Varunkumar Nagarajan