Matthew I
Matthew I

Reputation: 1123

Nested CSS-grid implicitly fill remaining height from parent grid

I am trying to have a child CSS-grid respect the dimensions of the parent grid. How would I be able to achieve that?

I was initially writing something like this:

.site,
body,
html {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}

.parent-grid {
  display: grid;
  height: 300px;
  width: 300px;
  grid-template-rows: 30px 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'nav' 'child';
  background-color: grey;
}

.nav {
  background-color: #0D47A1;
  grid-area: nav;
}

.child {
  grid-area: child;
}

.child-grid {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'test';
  background-color: grey;
}

.content {
  background-color: red;
  overflow: auto;
  grid-area: test;
}

* {
  box-sizing: border-box;
}
<div class="parent-grid">
  <div class="nav">Sidebar</div>
  <div class="child">
    <div class="child-grid">
      <div class="content">
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
      </div>
    </div>
  </div>
</div>

I would like to have 'content' be a scrollable area that doesn't expand the height of the parent (so it should be '270px').

Upvotes: 14

Views: 36984

Answers (3)

sol
sol

Reputation: 22949

The grid item (.child) is given min-height: auto by default. Apply min-height: 0 to .child to overrule this.

Then add height: 100% to .child-grid and overflow: auto to content...

.site,
body,
html {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}

.parent-grid {
  display: grid;
  height: 300px;
  width: 300px;
  grid-template-rows: 10vh 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'nav' 'child';
  background-color: grey;
}

.nav {
  background-color: #0D47A1;
  grid-area: nav;
}

.child {
  grid-area: child;
  min-height: 0;
}

.child-grid {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'test';
  background-color: grey;
  height: 100%;
}

.content {
  background-color: red;
  overflow: auto;
  grid-area: test;
}

* {
  box-sizing: border-box;
}
<div class="parent-grid">
  <div class="nav">Sidebar</div>
  <div class="child">
    <div class="child-grid">
      <div class="content">
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
      </div>
    </div>
  </div>
</div>

Upvotes: 15

Michael Benjamin
Michael Benjamin

Reputation: 371929

Here's a quick and simple solution with no changes to your HTML. Just add this to your code:

.child { 
   overflow: auto;
}

This overrides the min-height: auto default setting on grid items, allowing them to shrink below the size of their content and create overflow conditions.

Full explanation here: Prevent content from expanding grid items

.site,
body,
html {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}

.parent-grid {
  display: grid;
  height: 300px;
  width: 300px;
  grid-template-rows: 30px 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'nav' 'child';
  background-color: grey;
}

.nav {
  background-color: aqua;
  grid-area: nav;
}

.child {
  grid-area: child;
  overflow: auto;   /* NEW */
}

.child-grid {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'test';
  background-color: grey;
}

.content {
  background-color: red;
  overflow: auto;
  grid-area: test;
}

* {
  box-sizing: border-box;
}
<div class="parent-grid">
  <div class="nav">Sidebar</div>
  <div class="child">
    <div class="child-grid">
      <div class="content">
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
        <div>blah</div>
      </div>
    </div>
  </div>
</div>


Alternatively, instead of what you have here:

.parent-grid {
  display: grid;
  height: 300px;
  grid-template-rows: 30px 1fr;
}

Try this:

.parent-grid {
  display: grid;
  grid-template-rows: 30px 270px;
}

.content {
  overflow: auto;
  height: 100%;
}

I also removed an extra container (.child-grid) which doesn't appear to be necessary.

.site,
body,
html {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}

.parent-grid {
  display: grid;
  height: 300px;
  width: 300px;
  grid-template-rows: 30px 270px;
  grid-template-columns: 1fr;
  grid-template-areas: 'nav' 'child';
  background-color: grey;
}

.nav {
  background-color: aqua;
  grid-area: nav;
}

.child {
  grid-area: child;
}

.content {
  background-color: red;
  overflow: auto;
  height: 100%;
}

* {
  box-sizing: border-box;
}
<div class="parent-grid">
  <div class="nav">Sidebar</div>
  <div class="child">
    <div class="content">
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
      <div>blah</div>
    </div>
  </div>
</div>

Upvotes: 10

Frank N
Frank N

Reputation: 10416

Well, give a dedicated height to your child grid:

height: 240px;

and set

overflow: auto;

So, indeed, height is ensured. And if necessary, scrollbars will appear. Not sure, if the fairly recent feature of css grids is really the best thing to use here. You may want to have a look at flexbox: https://codepen.io/fnocke/details/RxMKOK

Or –even more compatible– you could indeed stick with normal display: block;. As long as you specify heights and set the overflow, that should do as well.

Upvotes: 0

Related Questions