0

I am attempting to use CSS Flexbox (display: flex) to take up the remaining height of a window. I also want scrolling available... Maybe I have been going about this wrong, but have been looking for so long that other options have eluded me.

The idea is that there is a fixed container. Within that fixed container is a flexbox that takes up 100% of the height. I add items to the flex box that stack in a column. The last item I add (container-wrapper) has dynamic content inside that will replace HTML through AJAX calls (else I would just move the action-bar outside the wrapper and be done with it). This content wrapper is also a flex container (as well as a flex item) and set to grow and shrink with the height of the window. The last item of this flex container is supposed to allow scrolling as the window shrinks.

Demo here.

<!-- The fixed container -->
<div class="fixed">
    <!-- The first flex container - direction: column -->
    <div class="outer">
        <div class="some-flex-item"></div>
        <div class="some-flex-item"></div>
        <!-- Grow and shrink with 100% of height -->
        <div class="container-wrapper">
            <!-- inner HTML is dynamic -->
            <!-- flex: 0 0 auto -->
            <div class="action-bar"></div>

            <!-- Want this div to take up remaining height of window
                 and have overflow-y scrolling -->
            <div class="container">
                ...
            </div>
        </div>
    </div>
</div>

Seems to work in IE 10+, Chrome, but Firefox doesn't add the scrollbar because container-wrapper's height grows unbounded due to the content inside. I should mention that an older version of Firefox displayed correctly (I think ~33), but updated versions do not.

I found a workaround where I make inner container position: relative and then wrap the inner contents of that in a div with absolute positioning set to 0 for top, left, bottom, right. Example here. I don't like this as it seems to defeat the purpose of flexbox layout. Is there any way to get this concept to play nicely across browser without having to do markup hacks?

Patrick
  • 6,828
  • 3
  • 23
  • 31

1 Answers1

6

Add this:

.container-wrapper {
    min-height: 0;
}

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
html, body {
  margin: 0;
  height: 100%;
}
.fixed {
  position: fixed;
  top: 60px;
  right: 0;
  bottom: 0;
  width: 100%;
  max-width: 400px;
}
.outer {
  border: 1px solid black;
  height: 100%;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-direction: column;
  flex-direction: column;
}
.outer > * {
  -ms-flex: 0 0 auto;
  flex: 0 0 auto;
}
.container-wrapper {
  -ms-flex: 1 1 100%;
  flex: 1 1 100%;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-direction: column;
  flex-direction: column;
  min-height: 0;
}
.action-bar {
  -ms-flex: 0 0 auto;
  flex: 0 0 auto;
  border-top: 1px solid silver;
  border-bottom: 1px solid silver;
  padding: 20px;
  text-align: right;
}
.container {
  -ms-flex: 1 1 100%;
  flex: 1 1 100%;
  overflow-y: auto;
}
.list {
  display: -ms-flexbox;
  display: flex;
  padding-top: 10px;
  padding-bottom: 10px;
  border: 1px solid aqua;
}
.display-name {
  -ms-flex: 1 1 100%;
  flex: 1 1 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  padding-right: 8px;
}
.display-date {
  -ms-flex: 0 0 auto;
  flex: 0 0 auto;
}
<div class="fixed">
  <div class="outer">
    <div>
      <p>Title</p>
    </div>
    <!-- The inner contents of container-wrapper is dynamic so I cannot
simply move the action-bar item outside -->
    <div class="container-wrapper">
      <div class="action-bar">
        <button>I don't do anything but occupy space</button>
      </div>
      <!-- Firefox allows this element to grow beyond the remaining space of the container-wrapper
thus expanding the height of the container-wrapper and not allowing scroll -->
      <div class="container">
        <div class="list">
          <div class="display-name">
            Display Name
          </div>
          <div class="display-date">
            Mar 31, 2015
          </div>
        </div>
        <div class="list">
          <div class="display-name">
            Really long name that should be truncated. I don't know
          </div>
          <div class="display-date">
            Mar 31, 2015
          </div>
        </div>
        <div class="list">
          <div class="display-name">
            Display Name
          </div>
          <div class="display-date">
            Mar 31, 2015
          </div>
        </div>
        <div class="list">
          <div class="display-name">
            Display Name
          </div>
          <div class="display-date">
            Mar 31, 2015
          </div>
        </div>
        <div class="list">
          <div class="display-name">
            Display Name
          </div>
          <div class="display-date">
            Mar 31, 2015
          </div>
        </div>
      </div>  
    </div>
  </div>
</div>

You need it because the Flexbox module changes the initial value of min-height:

4.5 Implied Minimum Size of Flex Items

To provide a more reasonable default minimum size for flex items, this specification introduces a new auto value as the initial value of the min-width and min-height properties defined in CSS 2.1.

Oriol
  • 274,082
  • 63
  • 437
  • 513