Css grid auto sized row content with overflow
Asked Answered
H

5

8

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>
Hophead answered 22/6, 2019 at 17:13 Comment(1)
I also made a jsfiddle examle for this jsfiddle.net/bgolyoo/ezd2usohHophead
A
6

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:

Alight answered 22/6, 2019 at 18:51 Comment(1)
Thank you, I like your answer the most. I think I was going about this whole thing wrong, and this answer shows where. I will try to set some explicit height for the overflow container, though I was hoping for it to be auto sized with the available space left.Hophead
P
0

I think this is what you meant by wanting it to be scrollable, here is my solution,

I changed the max-height to 100vh, which will fix the .container class's height to the height of the screen

I added overflow: scroll to make the any content exceeds the class .container height scrollable

.container {
  max-height: 100vh;
  overflow: scroll;


  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;
}
Pinzler answered 22/6, 2019 at 17:30 Comment(1)
I think I need to specify some things. So the example uses 100vh on the body, but I don't want to set that on the container. Also as I stated, I'd like the whole structure to be in the viewport, and only the inner content with class content__inner to be scrollable.Hophead
B
0

you need to maintain space of header and footer from layout of 100vh than your .content__inner fit as 100vh... let me explaining you with add one line to your code. edited code

i've added below code to your code

.content__inner { max-height: calc(100vh - 96px); /* added max height */ }

so container have the height of its parent, whatever and it's but never goes our of 100vh and fix as your requirement of scrolling

Bahaism answered 22/6, 2019 at 18:15 Comment(0)
M
0

Your HTML file:

<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-mod">
        <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>

your Css file:

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

.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: auto;
  height: calc(100vh - 74px);
}

.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);
}

I hope this works for you. :))

Mirilla answered 22/6, 2019 at 18:16 Comment(0)
C
0

You can use

.flex {
  display: flex;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

display: grid;
grid-template-columns: max-content auto;

<div>some title</div>
<div className="flex">some description</div>
Coyote answered 14/4, 2023 at 12:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.