3

I am trying to make a simple HTML/CSS based chat UI, where there are three vertical divs: Header, Chats, and Send Bar.

enter image description here

If I have three divs, how can I the middle div be the full "middle" height, and still be scrollable for scrolling messages? I can do this if I set the send bar div to a static height, but if I want it to be growable, that approach doesn't work.

Does anyone know how to use css to make a responsive chat-like UI such that the middle content is scrollable and the send bar content is growable?

I don't think it matters, but this is a React app.

Here is a code example of the issues I am seeing: (a) the lower div isn't sticky to the view, and (b), the middle div isn't scrollable.

See fiddle and snippet:

.wrapper {
 position: absolute;
 width: 100%;
 height: 100%;
 top: 0;
 left: 0;
 display: flex;
 flex-direction: column;
}

.top {
 height: 10px;
 background: yellow;
}

.bottom {
 background: gray;
}

.middle {
 background: red;
 width: 100%;
 height: 100%;
}
<div class="wrapper">
  <div class="top">

  </div>
  <div class="middle">
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    
  </div>
  <div class="bottom">
    <p>
    some content
    </p>
  </div>
</div>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
Brett
  • 11,637
  • 34
  • 127
  • 213
  • 2
    You should provide code snippets not screenshots. – gergana May 14 '19 at 15:18
  • https://stackoverflow.com/questions/40020921/flexbox-fill-available-space-vertically/ – kukkuz May 14 '19 at 15:31
  • see changes to your code: https://jsfiddle.net/gnfvxmu4/ based on the above question... – kukkuz May 14 '19 at 15:54
  • 1
    @kukkuz That did it. Post that in an answer, and I'll happily accept. Looks like I was overlooking the `overflow: auto`. Thank you! – Brett May 14 '19 at 16:01
  • Well, the other one doesn't have the `overflow: auto`, which was the culprit for having the middle be scrollable in this case. So it doesn't actually answer my question as-is. However, yes, I agree they are both related. – Brett May 14 '19 at 16:07
  • have added answer with detailed explanation, thank you – kukkuz May 15 '19 at 02:53

3 Answers3

5

Absolute positioning for your wrapper is not really necessary here. Also specifying height: 100% for the middle does not *fill the remaining space left by the top and the middle.

  • set the height of you flexbox to the viewport height so that the flexbox knows the height it needs to stretch to,

  • add flex: 1 to the middle section to fill the remaining space (You can refer this answer to see a simple demo of this),

  • add overflow: auto to the middle section - note that overflow value other than visible or resetting min-height to zero will override the default min-height: auto for a column flexbox. - read more details here: Why don't flex items shrink past content size? (see some examples of this behavior here and here.)

  • also add flex: 0 0 auto to bottom element so that in edge cases we can ensure that the it doesn't grow or shrink in any case.

See demo below:

body {
  margin: 0; /* reset default body margin */
}
.wrapper {
  height: 100vh; /* full viewport height */
  display: flex;
  flex-direction: column;
}

.top {
  background: yellow;
}

.bottom {
  background: gray;
  flex: 0 0 auto; /* don't grow or shrink in any case */
}

.middle {
  background: red;
  flex: 1; /* fill the remaining space */
  min-height: 0; /* optional */
  overflow: auto; /* overflow if exceeds available space */
}
<div class="wrapper">
  <div class="top">
    Header
  </div>
  <div class="middle">
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    <p>
     Test
    </p>
    
  </div>
  <div class="bottom">
    <p>
    some content
    </p>
  </div>
</div>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
1

Here's one way using flexbox:

#flexbox_container {
  display: flex;
  flex-direction: column;
  box-shadow: 0 4px 5px -2px #999;
  height: 90%;
}

.flex_item {
  background: #eee;
  margin: 4px;
  padding: 10px;
}

.middle {
  flex-grow: 1;
  overflow: auto;
}

html,
body {
  height: 100%;
}
<div id="flexbox_container">
  <div class="flex_item">
    Item</div>
  <div class="flex_item middle">
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
    <p>item</p>
  </div>
  <div class="flex_item">Item</div>
</div>
j08691
  • 204,283
  • 31
  • 260
  • 272
0

You probably want:

.wrapper {
 position: absolute;
 width: 100%;
 height: 100%;
 top: 0;
 left: 0;
 display: flex;
 flex-direction: column;
}

.top {
 height: 10px;
 background: yellow;
}

.bottom {
 background: gray;
}

.middle {
 background: red;
 width: 100%;
 height: 100%;
  overflow-y: auto;
}
<div class="wrapper">
  <div class="top">

  </div>
  <div class="middle">
    <p>
    some content
    </p>
        <p>
    some content
    </p>
        <p>
    some content
    </p>
        <p>
    some content
    </p>
        <p>
    some content
    </p>
        <p>
    some content
    </p>
        <p>
    some content
    </p>
            <p>
    some content
    </p>
  </div>
  <div class="bottom">
    <p>
    some content
    </p>
  </div>
</div>
Lu Chinke
  • 622
  • 2
  • 8
  • 27
  • The problem is that the middle div isn't scrollable, nor is the bottom div static. Which are the two problems I am trying to solve. I made a jsfiddle to showcase the issue: https://jsfiddle.net/Lv9dw3r1/ – Brett May 14 '19 at 15:42
  • just add 'overflow-y: auto;' into the css. I edited the snippet. – Lu Chinke May 14 '19 at 16:11