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 { flex: 1 1 20%; display: flex; flex-direction: column; overflow: auto; } #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; } .bubble p { border-radius: 5px; padding: 8px; margin: 8px 12px; max-width: 80%; position: relative; transition: background-color 0.5s; } .left p { background-color: #ccc; float: left; } .right p { background-color: #33c; color: #fff; float: right; } .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>
source share