Keep overflow div scrolled to bottom unless user scrolls up

Keep overflow div scrolled to bottom unless user scrolls up

I have a div that is only 300 pixels big and I want it to when the page loads scroll to the bottom of the content. This div has content dynamically added to it and needs to stay scrolled all the way down. Now if the user decides to scroll up I don’t want it to jump back to the bottom until the user scrolls all the way down again
Is it possible to have a div that will stay scrolled to the bottom unless the user scrolls up and when the user scrolls back to the bottom it needs to keep itself at the bottom even when new dynamic content is added. How would I go bout creating this.

Solutions/Answers:

Solution 1:

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;
});

Solution 2:

I just implemented this and perhaps you can use my approach.

Related:  Q: Angular2: 'switchMap' does not exist on type 'Observable'

Say we have the following HTML:

<div id="out" style="overflow:auto"></div>

Then we can check if it scrolled to the bottom with:

var out = document.getElementById("out");
// allow 1px inaccuracy by adding 1
var isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1;

scrollHeight gives you the height of the element, including any non visible area due to overflow. clientHeight gives you the CSS height or said in another way, the actual height of the element. Both methods returns the height without margin, so you needn’t worry about that. scrollTop gives you the position of the vertical scroll. 0 is top and max is the scrollHeight of the element minus the element height itself. When using the scrollbar it can be difficult (it was in Chrome for me) to get the scrollbar all the way down to the bottom. so I threw in a 1px inaccuracy. So isScrolledToBottom will be true even if the scrollbar is 1px from the bottom. You can set this to whatever feels right to you.

Related:  How to stub exported function in ES6?

Then it’s simply a matter of setting the scrollTop of the element to the bottom.

if(isScrolledToBottom)
    out.scrollTop = out.scrollHeight - out.clientHeight;

I have made a fiddle for you to show the concept: http://jsfiddle.net/dotnetCarpenter/KpM5j/

EDIT:
Added code snippet to clarify when isScrolledToBottom is true.

Stick scrollbar to bottom

const out = document.getElementById("out")
let c = 0

setInterval(function() {
    // allow 1px inaccuracy by adding 1
    const isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1

    const newElement = document.createElement("div")

    newElement.textContent = format(c++, 'Bottom position:', out.scrollHeight - out.clientHeight,  'Scroll position:', out.scrollTop)

    out.appendChild(newElement)

    // scroll to bottom if isScrolledToBottom is true
    if (isScrolledToBottom) {
      out.scrollTop = out.scrollHeight - out.clientHeight
    }
}, 500)

function format () {
  return Array.prototype.slice.call(arguments).join(' ')
}
#out {
    height: 100px;
}
<div id="out" style="overflow:auto"></div>
<p>To be clear: We want the scrollbar to stick to the bottom if we have scrolled all the way down. If we scroll up, then we don't want the content to move.
</p>

Solution 3:

I was able to get this working with CSS only.

The trick is to use display: flex; and flex-direction: column-reverse;

The browser treats the bottom like its the top. Assuming the browsers you’re targeting support flex-box, the only caveat is that the markup has to be in reverse order.

Related:  How to redirect to an external URL from angular2 route without using component?

Here is a working example. https://codepen.io/jimbol/pen/YVJzBg

Solution 4:

$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);

Live demo: http://jsfiddle.net/KGfG2/

Solution 5:

$('#div1').scrollTop($('#div1')[0].scrollHeight);

Or animated:

$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);

Solution 6:

$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;

This will calculate the ScrollTop Position from the height of #yourDivID using the $(document).height() property so that even if dynamic contents are added to the div the scroller will always be at the bottom position. Hope this helps. But it also has a small bug even if we scroll up and leaves the mouse pointer from the scroller it will automatically come to the bottom position. If somebody could correct that also it will be nice.