I have chat and I need to scroll all content to bottom. I want to use justify-content: flex-end and to have vertical scrollbar.
I just had to face this issue myself and, after concluding it is a bug, I came up with a workaround.
In summary, don't use justify-content: flex-end but rather put a margin-top: auto on the first child. Unlike flex-end this doesn't break the scrollbar functionality, and it bottom-aligns the contents when they're not overflowing the container.
Example based on @SrdjanDejanovic's fiddle is at https://jsfiddle.net/peter9477/4t5r0t5b/
In case the example isn't available, here's the relevant CSS:
#container {
overflow-y: auto;
display: flex;
flex-flow: column nowrap;
/* justify-content: flex-end; DO NOT USE: breaks scrolling */
}
#container > :first-child {
margin-top: auto !important;
/* use !important to prevent breakage from child margin settings */
}
An alternative workaround that I believe I've also used is to add an extra container for the scrollbar. Use the flex-end on the inner container and have the outer container handle the scrolling. I generally dislike workarounds that require adding dummy elements though, so I prefer my CSS-only solution above.
You have to turn .session-textchat into a flex column then margin-top: auto on .past-messages to send it to the bottom. Then play with overflow-y: scroll and some jQuery:
function updateScroll() {
$("#chat").animate({ scrollTop: $('#chat').prop("scrollHeight")}, 1000);
}
updateScroll();
$("#send_button").on('click', updateScroll);
.session-textchat {
display: flex;
flex-direction: column;
height: 300px;
margin-bottom: 30px;
background: #fff;
overflow-y: scroll;
}
.session-textchat .past-messages {
margin-top: auto;
width: 100%;
max-width: 980px;
}
.session-textchat .past-messages .receiver,
.session-textchat .past-messages .sender {
width: 100%;
min-height: 47px;
margin: 0 0 20px 0;
}
.session-textchat .past-messages .receiver .message,
.session-textchat .past-messages .sender .message {
position: relative;
padding: 15px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.session-textchat .past-messages .receiver {
text-align: left;
}
.session-textchat .past-messages .receiver .message {
background: #f4f4f4;
color: #535353;
}
.session-textchat .past-messages .sender {
text-align: right;
}
.session-textchat .past-messages .sender .message {
background: url("../img/rgbapng/0050ff26.png");
background: rgba(0, 80, 255, 0.15);
color: #0050ff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div id="chat" class="session-textchat">
<div class="past-messages">
<div class="receiver">
<span class="message">
Good afternoon David. Welcome to your appointment! How are you today?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="5" id="msg"></textarea>
</div>
<div class="form-group text-center">
<button href="#" id="send_button" class="btn btn-success">Send message</button>
</div>
</div>
Look at this full-screen jsFiddle.
Probably you've already solved this, but I faced this problem too and found a solution by trial and error, so I'm going to share it.
Having parent container's display set to flex display: flex and child's items align to flex-end align-items: flex-end will prevent overflow-y: auto to work.
Instead, you can leave you can use next CSS properties for your parent container (in your case session-textchat):
display: flex;
flex-direction: column-reverse; /* 'column' for start, 'column-reverse' for end */
overflow-y: scroll; /* or overflow-y: auto ... */
This will make your child div appear on the bottom of parent container (it will act like flex-end) and enable vertical scroll if content height is bigger than parent container.
I made a little jsfiddle for you if this sounds confusing: https://jsfiddle.net/lbartolic/9od4nruy/3/
In jsfiddle you can see header part, content part and footer. Container has fixed height and each part takes required height to fill the container. Content part _b__content will be scrollable if its content is taller than _b__content's height.
I hope this will help someone. Cheers.
It seems to be a common bug among the browsers.
You should distribute your style onto 2 containers: the outer will be scrolled, and the inner will be a flex container. Also, you need some js to keep your message list scrolled to bottom while adding new messages.
Here is an example of code:
markup:
<div id='outer'>
<div id='inner-scroll'>
<div id='inner-flex'>
<div class='flex-item'>Item 1</div>
<div class='flex-item'>Item 2</div>
...
</div>
</div>
style:
#inner-scroll {
height: 100%;
overflow: auto;
}
#inner-flex {
display: flex;
flex-direction: column;
justify-content: flex-end;
min-height: 100%;
}
.flex-item { /*nothing*/ }
JS:
function messagePushCallback()
{
var scrollable=document.getElementById('inner-scroll');
scrollable.scrollTo(0, scrollable.scrollHeight-scrollable.clientHeight);
}
// for an example
chat.onMessagePush(messagePushCallback);
window.addEventListener('load', messagePushCallback);
In JS, scrollable.scrollHeight shows the whole height of the element, including the space beyond its visible part, while scrollable.clientHeight is for the height of the visible part.
Also There is also another Solution
Remove the justify-content and add flex: 1 1 auto; property to the first element(create an empty div)
HTML
<div class="content-reversed">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
CSS
.content-reversed {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
HTML
<div class="content-reversed">
<div class="fix"></div> //add this dummy div
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
CSS
.content-reversed {
display: flex;
flex-direction: column;
}
.content-reversed .fix {
flex: 1 1 auto;
}