Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Css grid auto sized row content with overflow

I've been having problems with implementing a nested grid structure. This is a simplified example. As you can see the nested structure gives the height for the outer structure, thus growing outside the body. What I'd like to achieve is to make the .content__inner element, and only that element scrollable. Everything else should be inside the viewport. How can I achieve that?

Edit 1: Just to clarify, I'm using 100vh on the body, but don't want to set it on the container. The container should have the height of its parent, whatever it is.

body {
  display: block;
  height: 100vh;
  width: 100%;
  background-color: white;
  margin: 0;
}

.container {
  max-height: 100%;
  display: grid;
  grid-template-areas: "header header" "side content" "footer footer";
  grid-template-columns: 50px auto;
  grid-template-rows: min-content minmax(min-content, max-content) min-content;
}

.header {
  grid-area: header;
  background-color: rgba(255, 255, 0, 0.3);
}

.side {
  grid-area: side;
  background-color: rgba(0, 255, 0, 0.3);
}

.content {
  grid-area: content;
  background-color: rgba(0, 0, 255, 0.3);
}

.overflow {
  overflow: auto;
}

.content-item {
  height: 20px;
  margin-bottom: 5px;
  background-color: white;
}

.footer {
  grid-area: footer;
  background-color: rgba(255, 0, 255, 0.3);
}
<div class="container">
  <div class="header">header</div>
  <div class="side">side</div>
  <div class="content">

    <div class="container container__inner">
      <div class="header header__inner">header</div>
      <div class="side side__inner">side</div>
      <div class="content content__inner overflow">
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
      </div>
      <div class="footer footer__inner">footer</div>
    </div>

  </div>
  <div class="footer">footer</div>
</div>
like image 727
bodorgergely Avatar asked Jun 22 '19 17:06

bodorgergely


People also ask

How do you set auto height on grid?

To allow the grid to auto-size it's height to fit rows, set grid property domLayout='autoHeight' .

How do I make my display grid responsive?

Building a Responsive Grid-View First ensure that all HTML elements have the box-sizing property set to border-box . This makes sure that the padding and border are included in the total width and height of the elements. Read more about the box-sizing property in our CSS Box Sizing chapter.

How do I make my row height fit content?

Change the row height to fit the contents Select the row or rows that you want to change. On the Home tab, in the Cells group, click Format. Under Cell Size, click AutoFit Row Height.

How does auto-placement in CSS grid work?

Auto-placement by column In this case grid will add items in rows that you have defined using grid-template-rows . When it fills up a column it will move onto the next explicit column, or create a new column track in the implicit grid. As with implicit row tracks, these column tracks will be auto sized.


1 Answers

The problem is easy to describe, but may not have a simple solution (depending on your requirements).

The problem is actually clear to see in the title itself:

Css grid auto sized row content with overflow

Auto-sized elements cannot overflow. They are auto sized. This means the element shrinks and expands based on its content size, never having a need to overflow.

There has to be something that sets a fixed length on the container. A boundary that can be crossed, thus triggering an overflow condition.

From MDN:*

In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.

Your row heights are insufficient to trigger an overflow:

grid-template-rows: min-content minmax(min-content, max-content) min-content

But something like this would work:

  grid-template-rows: 10% 80% 10%

Unfortunately, the code above only works in Chrome. For the layout to also work in Firefox and Edge, do this:

  grid-template-rows: 10% minmax(0, 80%) 10%

body {
  display: block;
  height: 100vh;
  width: 100%;
  background-color: white;
  margin: 0;
}

.container {
  max-height: 100%;
  display: grid;
  grid-template-areas: "header header" "side content" "footer footer";
  grid-template-columns: 50px auto;
  grid-template-rows: 10% minmax(0, 80%) 10%; /* adjustment */
}

.header {
  grid-area: header;
  background-color: rgba(255, 255, 0, 0.3);
}

.side {
  grid-area: side;
  background-color: rgba(0, 255, 0, 0.3);
}

.content {
  grid-area: content;
  background-color: rgba(0, 0, 255, 0.3);
}

.overflow {
  overflow: auto;
}

.content-item {
  height: 20px;
  margin-bottom: 5px;
  background-color: white;
}

.footer {
  grid-area: footer;
  background-color: rgba(255, 0, 255, 0.3);
}
<div class="container">
  <div class="header">header</div>
  <div class="side">side</div>
  <div class="content">
    <div class="container container__inner">
      <div class="header header__inner">header</div>
      <div class="side side__inner">side</div>
      <div class="content content__inner overflow">
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
      </div>
      <div class="footer footer__inner">footer</div>
    </div>
  </div>
  <div class="footer">footer</div>
</div>

Basically, you need to find some way to set a fixed height limit on the overflow row for the scrollbar to function.


For an explanation of the browser differences described above see these posts:

  • Prevent content from expanding grid items
  • How come minmax(0, 1fr) works for long elements while 1fr doesn't?
like image 164
Michael Benjamin Avatar answered Oct 13 '22 15:10

Michael Benjamin