Scrollable div to stick to bottom, when outer div changes in size
2:nd revision of this answer
Your friend here is flex-direction: column-reverse;
which does all you ask while align the messages at the bottom of the message container, just like for example Skype and many other chat apps do.
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
The downside with flex-direction: column-reverse;
is a bug in IE/Edge/Firefox, where the scrollbar doesn't show, which your can read more about here: Flexbox column-reverse and overflow in Firefox/IE
The upside is you have ~ 90% browser support on mobile/tablets and ~ 65% for desktop, and counting as the bug gets fixed, ...and there is a workaround.
// scroll to bottom
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
// only shift-up if at bottom
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
In the below code snippet I've added the 2 functions from above, to make IE/Edge/Firefox behave in the same way flex-direction: column-reverse;
does.
function addContent () { var msgdiv = document.getElementById('messages'); var msgtxt = document.getElementById('inputs'); var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.value.length > 0) { msgdiv.innerHTML += msgtxt.value + '<br/>'; msgtxt.value = ""; } else { msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>'; } /* if at bottom and is IE/Edge/Firefox */ if (atbottom && (!isWebkit || isEdge)) { updateScroll(msgdiv); }}
function resizeInput () { var msgdiv = document.getElementById('messages'); var msgtxt = document.getElementById('inputs'); var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.style.height == '120px') { msgtxt.style.height = 'auto'; } else { msgtxt.style.height = '120px'; } /* if at bottom and is IE/Edge/Firefox */ if (atbottom && (!isWebkit || isEdge)) { updateScroll(msgdiv); }}
/* fix for IE/Edge/Firefox */var isWebkit = ('WebkitAppearance' in document.documentElement.style);var isEdge = ('-ms-accelerator' in document.documentElement.style);var tempCounter = 6;
function updateScroll(el){ el.scrollTop = el.scrollHeight;}function scrollAtBottom(el){ return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));}
html, body { height:100%; margin:0; padding:0; }
.chat-window{ display:flex; flex-direction:column; height:100%;}.chat-messages{ flex: 1; height:100%; overflow: auto; display: flex; flex-direction: column-reverse;}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
/* temp. buttons for demo */button { width: 12%; height: 44px; margin-left: 5%; vertical-align: top; }
/* begin - fix for hidden scrollbar in IE/Edge/Firefox */.chat-messages-text{ overflow: auto; }@media screen and (-webkit-min-device-pixel-ratio:0) { .chat-messages-text{ overflow: visible; } /* reset Edge as it identifies itself as webkit */ @supports (-ms-accelerator:true) { .chat-messages-text{ overflow: auto; } }}/* hide resize FF */@-moz-document url-prefix() { .chat-input-text { resize: none } }/* end - fix for hidden scrollbar in IE/Edge/Firefox */
<div class="chat-window"> <div class="chat-messages"> <div class="chat-messages-text" id="messages"> Long long content 1!<br/> Long long content 2!<br/> Long long content 3!<br/> Long long content 4!<br/> Long long content 5!<br/> </div> </div> <div class="chat-input"> <textarea class="chat-input-text" placeholder="Type your message here..." id="inputs"></textarea> <button onclick="addContent();">Add msg</button> <button onclick="resizeInput();">Resize input</button> </div></div>
height: 100% foils flexbox stick scrollbar to bottom unless moved
I couldn't get this to work using the method I describe in the question. See @kukkuz's answer that "you can't do that... in flexbox", that the fixed size is basically a requirement for it to work. Not only that, but even keeping fixed size I found that the basic example seems to lose its ability to stick to the bottom if you deviate slightly from the code in the snippet I quote.
What I found that did work was to flip it upside down (text upside down, everything), then flip it back in an outer container. The method was suggested by this answer:
https://stackoverflow.com/a/34345634
This transformation makes the browser think the scroll bottom is actually the top. Pinning to the top is easier for it to do than getting pinned to the bottom (since it can be modeled as the constant value 0, as opposed to an ever-growing number).
Pretty weird, but it appears to work in the browsers I've tried!
Keep overflow div scrolled to bottom unless user scrolls up
This might help you:
var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
[EDIT], to match the comment...
function updateScroll(){
var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
}
whenever content is added, call the function updateScroll(), or set a timer:
//once a second
setInterval(updateScroll,1000);
if you want to update ONLY if the user didn't move:
var scrolled = false;
function updateScroll(){
if(!scrolled){
var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
}
}
$("#yourDivID").on('scroll', function(){
scrolled=true;
});
Position sticky to bottom of scrollable element
You need to change the display of the .container
to flex
display: flex;
flex-direction: column;
And the .footer
needs to have a margin-top: auto;
See code here:
.container {
position: relative;
overflow-y: scroll;
height: 150px;
border: solid 1px black;
display: flex;
flex-direction: column;
}
.footer {
position: sticky;
right: 0;
bottom: 0;
float: right;
background-color: lightblue;
margin-top: auto;
}
<div class="container">
<table>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
</table>
<div class="footer">Footer</div>
</div>
<br/>
<div class="container">
<table>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>Hello</td></tr>
</table>
<div class="footer">Footer</div>
</div>
how do I always keep my html element stick to bottom of parent element,I am using overflow:hidden and giving height implicitly to parent element?
Wrap the note div in another div. Give the new div (parent) a relative positioning. Give the button in the child div an absolute position.
THis should solve your problem.
I made a JSFiddle to illustrate this: http://jsfiddle.net/koder613/18dt3yhL/8/
HTML(JSX):
<div className="noteParent">
<div className="note">
<h1>{props.title}</h1>
<p>{props.content}</p>
<button onClick={deleteNoteInNote}>
{" "}
<DeleteIcon />{" "}
</button>
</div>
</div>
CSS:
.noteParent {
width:200px;
height: 150px;
position:relative;
}
.note {
height:100%;
overflow: auto;
}
.note button{
position:absolute;
bottom:0;
right:1rem;
}
How to change a scrolling element behavior on resize? (HTML, CSS, JavaScript)
This can be done using CSS, as I showed in this answer.
And here is the code part which make it happen.
html, body { height:100%; margin:0; padding:0; }
.chat-window{ display:flex; flex-direction:column; height:100%;}.chat-messages{ flex: 1; height:100%; overflow: auto; display: flex; flex-direction: column-reverse;}
/* begin - fix for hidden scrollbar in IE/Edge/Firefox */.chat-messages-text{ overflow: auto; }@media screen and (-webkit-min-device-pixel-ratio:0) { .chat-messages-text{ overflow: visible; } /* reset Edge as it identifies itself as webkit */ @supports (-ms-accelerator:true) { .chat-messages-text{ overflow: auto; } }}
<div class="chat-window"> <div class="chat-messages"> <div class="chat-messages-text" id="messages"> Long long content 1!<br/> Long long content 2!<br/> Long long content 3!<br/> Long long content 4!<br/> Long long content 5!<br/> Long long content 1!<br/> Long long content 2!<br/> Long long content 3!<br/> Long long content 4!<br/> Long long content 5!<br/> Long long content 1!<br/> Long long content 2!<br/> Long long content 3!<br/> Long long content 4!<br/> Long long content 5!<br/> Long long content 1!<br/> Long long content 2!<br/> Long long content 3!<br/> Long long content 4!<br/> Long long content 5!<br/> Long long content 1!<br/> Long long content 2!<br/> Long long content 3!<br/> Long long content 4!<br/> Long long content 5!<br/> </div> </div></div>
How to make the scrollbar always stick to the bottom when new data is added
[Edit]: I just found this codePen. It does exactly what you are looking for :)
I guess what you are looking for is :
window.scrollTo(0,document.body.scrollHeight);
instead of :
myRef.current.scrollTop = myRef.current.scrollHeight;
Of course, you need to change document.body.scrollHeight by the scrollable block. You can probably clean up a bit of code if your refs aren't used for anything else.
Here is the repro on Stackblitz. I only changed the line above from your own code.
P.S. : I got this answer from this SO thread :)
Make div stay at bottom of page's content all the time even when there are scrollbars
This is precisely what position: fixed
was designed for:
#footer {
position: fixed;
bottom: 0;
width: 100%;
}
Here's the fiddle: http://jsfiddle.net/uw8f9/
Related Topics
Get the Device Width in JavaScript
Can You Control Gif Animation With JavaScript
Ios 8 Removed "Minimal-Ui" Viewport Property, Are There Other "Soft Fullscreen" Solutions
Add/Remove Class With Jquery Based on Vertical Scroll
Set Webkit Keyframes Values Using JavaScript Variable
What Is the Cleanest Way to Disable CSS Transition Effects Temporarily
How to Build Simple Jquery Image Slider With Sliding or Opacity Effect
Parsing CSS in JavaScript/Jquery
How to Have Content from an Iframe Overflow Onto the Parent Frame
Remove All Classes That Begin With a Certain String
Determine If an Element Has a CSS Class With Jquery
Fixed Positioning in Mobile Safari
Check Element CSS Display With JavaScript
Add Stylesheet to Head Using JavaScript in Body
Disable Drag and Drop on HTML Elements
Understanding the Difference Between Object.Create() and New Somefunction()