Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexbox overflow scrollbar displaying on body instead of inner elements

The Problem:

In a full-size app layout (100% width, 100% height) using flexbox with overflow, the scrollbars do not display for overflow-y in Firefox, IE, or Edge. They do display properly in Chrome. Rather than having a vertical scrollbar in FF/IE/Edge on the element, the scrollbar is applied to the entire page.

What I've Tried:

I've tried adding, as mentioned in several other SO answers, to add min-height: 0; to the flex elements / parents. I haven't been able to get this solution to work, but perhaps I am doing something wrong.

Screenshots:

Chrome:

enter image description here

Firefox:

enter image description here

Example:

https://codepen.io/gunn4r/pen/WEoPjN

html {
  height: 100%;
}

.flex-grow {
  flex: 1;
}

.canvas-wrapper {
  overflow: scroll;
}

.canvas {
  width: 3000px;
  height: 3000px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />

<body class="h-100">
  <div class="h-100 container-fluid d-flex flex-column">

    <div class="row bg-warning">
      <div class="col-12 py-4">Top Bar</div>
    </div>

    <div class="row no-gutter flex-grow">

      <div class="col-9 px-0 d-flex flex-column">
        <div class="canvas-wrapper">
          <div class="canvas bg-success">
            Canvas
          </div>
        </div>
        <div class="bg-danger py-3">
          Canvas Footer
        </div>
      </div>

      <div class="col-3 bg-primary">
        <div class="sidebar-item">Sidebar</div>
      </div>

    </div>

    <div class="row bg-warning">
      <div class="col-12 py-2">Overall Footer</div>
    </div>

  </div>
</body>
like image 876
gunn4r Avatar asked Aug 07 '17 16:08

gunn4r


2 Answers

It looks like the problem stems from this section of your code:

.canvas-wrapper {
  overflow: scroll;
}

You want this element to have scrollbars. However, the element has no defined height.

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.

Chrome doesn't seem to care about the height requirement. The other browsers do.

This should be enough to make it work across browsers:

.canvas-wrapper {
  overflow: scroll;
  flex: 1 0 1px;
}

html {
  height: 100%;
}

.flex-grow {
  flex: 1;
}

.canvas-wrapper {
  overflow: scroll;
  flex: 1 0 1px; /* NEW */
}

.canvas {
  width: 3000px;
  height: 3000px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<body class="h-100">
  <div class="h-100 container-fluid d-flex flex-column">

    <div class="row bg-warning">
      <div class="col-12 py-4">Top Bar</div>
    </div>

    <div class="row no-gutter flex-grow">
      
      <div class="col-9 px-0 d-flex flex-column">
         <div class="canvas-wrapper">
             <div class="canvas bg-success">
               Canvas
           </div>
        </div>
        <div class="bg-danger py-3">
          Canvas Footer
        </div>
      </div>
      
      <div class="col-3 bg-primary">
        <div class="sidebar-item">Sidebar</div>
      </div>
      
    </div>

    <div class="row bg-warning">
      <div class="col-12 py-2">Overall Footer</div>
    </div>

    </div>
</body>
like image 182
Michael Benjamin Avatar answered Oct 15 '22 17:10

Michael Benjamin


When using percent for height on element, all its ascendants also need a height set, and if all will have percent, one need to set it all the way up to the html/body.

When combined with Flexbox this can get really tricky to solve, as when one need to set height: 100% on all ascendants, other unwanted render issues can cause the layout to break.

Here is one solution, which work perfect cross browser, where an extra wrapper, canvas-fix, for the canvas is added, and then with position: absolute we can make this work.

Fiddle demo

Stack snippet

html {
  height: 100%;
}
.flex-grow {
  flex: 1;
}
.canvas-wrapper {
  flex-grow: 1;                     /*  take all remaining space  */
  width: 100%;                      /*  full width  */
  position: relative;               /*  for the absolute positioned fix  */
}
.canvas-fix {                       /*  added rule  */
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: scroll;
}
.canvas {
  width: 3000px;
  height: 3000px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />

<body class="h-100">
  <div class="h-100 container-fluid d-flex flex-column">

    <div class="row bg-warning">
      <div class="col-12 py-4">Top Bar</div>
    </div>

    <div class="row no-gutter flex-grow">

      <div class="col-9 px-0 d-flex flex-column">
        <div class="canvas-wrapper">
          <div class="canvas-fix">
            <div class="canvas bg-success">
               Canvas
            </div>
          </div>
        </div>
        <div class="bg-danger py-3">
          Canvas Footer
        </div>
      </div>

      <div class="col-3 bg-primary">
        <div class="sidebar-item">Sidebar</div>
      </div>

    </div>

    <div class="row bg-warning">
      <div class="col-12 py-2">Overall Footer</div>
    </div>

    </div>
</body>
like image 24
Asons Avatar answered Oct 15 '22 18:10

Asons