Can this flexbox? Chat window with entry below, chats scrolling up

It seems like this should be possible with flexbox, but I can't figure it out.

http://codepen.io/MichaelJCole/pen/NGBVGe

Goal:

  • textarea (for entering messages) stays at the bottom all the time.
  • chats start at the bottom, then scroll as needed.
  • If you use Google Hangouts, such as a messaging app.

Here's the markup:

<div id="chatBar"> <div id="chatList"> <div class="chat mine">hello world</div> <div class="chat theirs">hello moon</div> </div> <input id="chatBarInput" class="form-control" type="textarea"> </div> 

And here is the CSS:

 html, body { height: 100%; } #chatBar { height: 100%; display: flex; flex-flow: column nowrap; justify-content: flex-end; overflow: none; } #chatList { flex: 0 1 auto; display: flex; flex-flow: column nowrap; justify-content: flex-end; overflow-y: scroll; } #chatBarInput { flex: 1 0 auto; } .chat { flex: none; align-self: flex-start; background-color: lightgreen; } .chat.mine { align-self: flex-end; background-color: pink; } 

I cannot get #chatBar “squeeze” #chatList without setting the height. Which I tried to avoid using flexbox: - /

Sorry, I'm a coder. Tried a bunch of things and then shortened it for CodePen.

Looks like I should be able to scroll through the inner flexbox, leaving only the outer one. Should I use position: absolute?

+5
source share
2 answers

I cannot get #chatBar to “compress” #chatList without setting the height. Which I tried to avoid using flexbox

You had flex-basis set to auto for all elements. Without an explicit height, the flex model will automatically try to fit everything within the available space by reducing or expanding the elements. This is why you cannot get #chatList to work as intended. The div itself, as well as individual chats, expand or contract within the available space.

What you need to do is simple:

 #chatBar { height: 100%; overflow: hidden; display: flex; flex-flow: column; } #chatList { /* grow or shrink as required from flex-basis height of 20% */ flex: 1 1 20%; display: flex; flex-direction: column; overflow: auto; } /* do not grow or shrink with a flex-basis height of 80% */ #chatBarInput { flex: 0 0 80%; } 

And you can see how it works. Then you could take it further from here.

Your modified code: http://codepen.io/Abhitalks/pen/ZbjNvQ/


Goal:

  • textarea (for entering messages) stays at the bottom all the time.
  • chats start at the bottom, then scroll as needed.
  • If you use Google Hangouts, such as a messaging app.

The trick is to use flex-direction: column-reverse and add new messages to the container instead of adding them.

I took the old answer and changed the layout to a flexible model to demonstrate this. You can review the code to find out how to do this.

Demo script: http://jsfiddle.net/abhitalks/khj4903t/

Demo fragment:

 var btn = document.getElementById('btn'), inp = document.getElementById('inp'), chats = document.getElementById('chatWindow') ; btn.addEventListener('click', postMsg); inp.addEventListener('keyup', function(e) { if (e.keyCode == 13) { postMsg(); } }); function postMsg() { var msg = inp.value, bubble = document.createElement('div'), p = document.createElement('p'); if (msg.trim().length <= 0) { return; } bubble.classList.add('bubble'); bubble.classList.add('right'); p.textContent = msg; bubble.appendChild(p); inp.value = ''; chats.insertBefore(bubble, chats.firstChild); } 
 * { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; overflow: hidden; } .wrap { margin: 8px; height: 90%; width: 50%; display: flex; flex-direction: column; } .container { flex: 1 1 90%; display: flex; flex-direction: column; background-color: #eee; border: 1px solid #ccc; overflow: auto; } .form { flex: 0 0 32px; display: flex; border: 1px solid #ddd; } .form > input[type=text] { flex: 1 1 auto; border: 1px solid #eee; } .form > input[type=button] { flex: 0 0 20%; border: 1px solid #eee; } .bubble { flex: 1 1 auto; clear: both; } /* clear the floats here on parent */ .bubble p { border-radius: 5px; padding: 8px; margin: 8px 12px; max-width: 80%; /* this will make it not exceed 80% and then wrap */ position: relative; transition: background-color 0.5s; } .left p { background-color: #ccc; float: left; } /* floated left */ .right p { background-color: #33c; color: #fff; float: right; } /* floated right */ /* classes below are only for arrows, not relevant */ .left p::before { content: ''; position: absolute; width: 0; height: 0; left: -8px; top: 8px; border-top: 4px solid transparent; border-right: 8px solid #ccc; border-bottom: 4px solid transparent; } .right p::after { content: ''; position: absolute; width: 0; height: 0; right: -8px; bottom: 8px; border-top: 4px solid transparent; border-left: 8px solid #33c; border-bottom: 4px solid transparent; } 
 <div class="wrap"> <div id="chatWindow" class="container"> <div class="bubble left"><p>msg</p></div> <div class="bubble left"><p>long message</p></div> <div class="bubble right"><p>ultra long message which can wrap at eighty percent </p></div> <div class="bubble left"><p>lorem ipsum</p></div> <div class="bubble right"><p>very long message</p></div> <div class="bubble right"><p>one more message</p></div> <div class="bubble left"><p>lorem ipsum</p></div> <div class="bubble right"><p>another message</p></div> <div class="bubble left"><p>lorem ipsum</p></div> <div class="bubble right"><p>yet another message</p></div> <div class="bubble left"><p>lorem ipsum</p></div> </div> <div id="inputWindow" class="form"> <input id="inp" type="text" /> <input id="btn" type="button" value="Send" /> </div> </div> 
+10
source

A vertical scrollbar exists in the browser because you set height: 100% to body , and the default user agent stylesheet is margin for body , usually 8px. Thus, 100% + 16 pixels triggers vertical scrolling.

Add this to your CSS: body { margin: 0; } body { margin: 0; }

To apply a scrollbar to an internal flexbox ( .chatlist ), perform the following two settings:

 #chatList { flex: 0 1 75px; /* specify a height */ display: flex; flex-flow: column nowrap; /* justify-content: flex-end; REMOVE */ overflow-y: scroll; } 

DEMO: http://jsfiddle.net/5p2vy31p/1/

+1
source

Source: https://habr.com/ru/post/1235164/


All Articles