Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow one grid item to scroll with fixed header and sidebar

Tags:

html

css

css-grid

I have a grid layout with two columns and two rows. A sticky left nav, a sticky header, and content that will live in the bottom right corner of the grid.

What I have now is nearly there, but I would like the .content div to use scroll when content extends beyond the screen. I thought I would be able to just use overflow: auto, but that isn't working. Is what I have close?

body {
  margin: 0;
  overflow: hidden;
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 20vh auto;
  grid-template-areas: "nav header" "nav content";
}

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

.header {
  grid-area: header;
  background-color: grey;
}

.content {
  grid-area: content;
  height: 1000px; // This is dynamic
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
  <div>

JS fiddle

like image 624
sss Avatar asked Jan 05 '18 04:01

sss


People also ask

How do I fix the header grid?

With . wrapper {margin-top; 80px; position:relative;} and . header {position:fixed; height: 80px; z-index: 10;} a grid definition within . wrapper will flow beneath the fixed header.

How do I make my sidebar sticky?

Just call new StickySidebar('ELEMENT') on the element that you want it to be sticky when scrolling up/down inside their parent. var sidebar = new StickySidebar('#sidebar', {topSpacing: 20}); Scroll It!

Can you have nested grids in CSS?

Introduction to subgridYou can "nest" grids by making a grid item a grid container. These grids however are independent of the parent grid and of each other, meaning that they do not take their track sizing from the parent grid. This makes it difficult to line nested grid items up with the main grid.


3 Answers

For overflow: auto to work (i.e., for scrollbars to render) browsers need a trigger. This trigger is usually a height / width limitation that forces an overflow condition, which launches the scrollbars.

Trigger conditions vary among browsers. They also vary among CSS technologies, such as flex, grid and block layouts.

In this particular case, there are several logical places to establish an overflow condition, but none of them work.

  1. You could target the grid item, as you have tried:

    .content {
       height: 1000px
       overflow: auto;
    }
    

    But it doesn't work. No scrollbar appears on the fluid item.

body {
  margin: 0;
  /* overflow: hidden; */
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 20vh auto;
  grid-template-areas: "nav header" 
                       "nav content";
}

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

.header {
  grid-area: header;
  background-color: lightgrey;
}

.content {
  grid-area: content;
  height: 1000px;
  overflow: auto;
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
  <div>
  1. You could target the row itself, as I tested:

    .page {
       display: grid;
       grid-template-rows: 55px 1000px;
    }
    
    .content {
       overflow: auto;
    }
    

    But that doesn't work either. Still no scrollbar on the fluid item.

body {
  margin: 0;
  /* overflow: hidden; */
}

.page {
  display: grid;
  grid-template-rows: 55px 1000px;
  grid-template-columns: 20vh auto;
  grid-template-areas:
    "nav header"
    "nav content";
}

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

.header {
  grid-area: header;
  background-color: lightgrey;
}

.content {
  overflow: auto;
  grid-area: content;
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
  <div>
  1. So I targeted a child of the grid item. DING DING DING! That worked.

    No need for fixed positioning. No need for sticky positioning. This works across all browsers that support Grid Layout.

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: 55px calc(100vh - 55px);  /* height limitation on second row */
  grid-template-columns: 20vh auto;
  grid-template-areas: "nav header" 
                       "nav content";
}

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

.header {
  grid-area: header;
  background-color: lightgrey;
}

.content {
  grid-area: content;
  background-color: red;
  overflow: auto;                          /* overflow condition on parent */
}

article {
  height: 1000px;                          /* height set on child; triggers scroll */
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <article><!-- new section for content -->
      <h1>title</h1>
    </article>
  </div>
  <div>

jsFiddle demo

like image 126
Michael Benjamin Avatar answered Oct 01 '22 03:10

Michael Benjamin


Browser support is not 100%, but what about actually using sticky instead of fixed positioning? (now tested in Chrome) You won't have to deal with hard-coded margins.

One of the issues you'll still have to deal with, what to do when the content in your sidebar (.nav > div) Is higher than your viewport.

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 3.5rem auto;
  grid-template-areas: "nav header" "nav content";
}

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

.nav > div {
  position: sticky;
  top: 0;
}

.header {
  grid-area: header;
  background-color: grey;
  position: sticky;
  top: 0;
  min-height: 3.5rem;
}

.content {
  grid-area: content;
  min-height: 1000px;
  background-color: red;
}
<div class="page">
  <div class="nav">
    <div>Side nav</div>
  </div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
<div>
like image 42
René Avatar answered Oct 01 '22 03:10

René


I have included the change log to see where the code needs to be change in order to get an understanding. Also the full code snippet is available below. Hope this is what you expect.

Change log

*Remove body { overflow: hidden; }

*Change .page { grid-template-columns: 3.5rem auto; }

*Added

.nav { position: fixed;
      top: 0;
      bottom:0;}

*Added

.header {  position: fixed;
      margin-left: 3.5rem;
      width: 100%;
      height: 3.5rem; }

Full Code

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 3.5rem auto;
  grid-template-areas:
    "nav header"
    "nav content";
}

.nav {
  position: fixed;
  top: 0;
  bottom:0;
  grid-area: nav;
  background-color: blue;

}

.header {
  grid-area: header;
  background-color: grey;
  position: fixed;
  margin-left: 3.5rem;
  width: 100%;
  height: 3.5rem;
}

.content {
  grid-area: content;
  height: 1000px;
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
<div>
like image 30
Lakindu Gunasekara Avatar answered Oct 01 '22 04:10

Lakindu Gunasekara