Scroll to bottom of div?

Viewed 1059874

I am creating a chat using Ajax requests and I'm trying to get messages div to scroll to the bottom without much luck.

I am wrapping everything in this div:

#scroll {
    height:400px;
    overflow:scroll;
}

Is there a way to keep it scrolled to the bottom by default using JS?

Is there a way to keep it scrolled to the bottom after an ajax request?

34 Answers

Here's what I use on my site:

var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;

smooth scroll with Javascript:

document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });

alternative solution

function scrollToBottom(element) {
  element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}

Java Script:

document.getElementById('messages').scrollIntoView(false);

Scrolls to the last line of the content present.

You can use the HTML DOM scrollIntoView Method like this:

var element = document.getElementById("scroll");
element.scrollIntoView();

My Scenario: I had an list of string, in which I had to append a string given by a user and scroll to the end of the list automatically. I had fixed height of the display of the list, after which it should overflow.

I tried @Jeremy Ruten's answer, it worked, but it was scrolling to the (n-1)th element. If anybody is facing this type of issue, you can use setTimeOut() method workaround. You need to modify the code to below:

setTimeout(() => {
    var objDiv = document.getElementById('div_id');
    objDiv.scrollTop = objDiv.scrollHeight
}, 0)

Here is the StcakBlitz link I have created which shows the problem and its solution : https://stackblitz.com/edit/angular-ivy-x9esw8

Like you, I'm building a chat app and want the most recent message to scroll into view. This ultimately worked well for me:

//get the div that contains all the messages
let div = document.getElementById('message-container');

//make the last element (a message) to scroll into view, smoothly!
div.lastElementChild.scrollIntoView({ behavior: 'smooth' });

Scroll to the last element inside the div:

myDiv.scrollTop = myDiv.lastChild.offsetTop

If your project targets modern browsers, you can now use CSS Scroll Snap to control the scrolling behavior, such as keeping any dynamically generated element at the bottom.

    .wrapper > div {
        background-color: white;
        border-radius: 5px;
        padding: 5px 10px;
        text-align: center;
        font-family: system-ui, sans-serif;
    }

    .wrapper {
        display: flex;
        padding: 5px;
        background-color: #ccc;
        border-radius: 5px;
        flex-direction: column;
        gap: 5px;
        margin: 10px;
        max-height: 150px;

        /* Control snap from here */
        overflow-y: auto;
        overscroll-behavior-y: contain;
        scroll-snap-type: y mandatory;
    }

    .wrapper > div:last-child {
        scroll-snap-align: start;
    }
<div class="wrapper">
    <div>01</div>
    <div>02</div>
    <div>03</div>
    <div>04</div>
    <div>05</div>
    <div>06</div>
    <div>07</div>
    <div>08</div>
    <div>09</div>
    <div>10</div>
</div>

Why not use simple CSS to do this?

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

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

A very simple method to this is to set the scroll to to the height of the div.

var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);

On my Angular 6 application I just did this:

postMessage() {
  // post functions here
  let history = document.getElementById('history')
  let interval    
  interval = setInterval(function() {
    history.scrollTop = history.scrollHeight
    clearInterval(interval)
  }, 1)
}

The clearInterval(interval) function will stop the timer to allow manual scroll top / bottom.

You can use the Element.scrollTo() method.

It can be animated using the built-in browser/OS animation, so it's super smooth.

function scrollToBottom() {
    const scrollContainer = document.getElementById('container');
    scrollContainer.scrollTo({
        top: scrollContainer.scrollHeight,
        left: 0,
        behavior: 'smooth'
    });
}

// initialize dummy content
const scrollContainer = document.getElementById('container');
const numCards = 100;
let contentInnerHtml = '';
for (let i=0; i<numCards; i++) {
  contentInnerHtml += `<div class="card mb-2"><div class="card-body">Card ${i + 1}</div></div>`;
}
scrollContainer.innerHTML = contentInnerHtml;
.overflow-y-scroll {
  overflow-y: scroll;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>

<div class="d-flex flex-column vh-100">
  <div id="container" class="overflow-y-scroll flex-grow-1"></div>
  <div>
    <button class="btn btn-primary" onclick="scrollToBottom()">Scroll to bottom</button>
  </div>
</div>

Css only:

.scroll-container {
  overflow-anchor: none;
}

Makes it so the scroll bar doesn't stay anchored to the top when a child element is added. For example, when new message is added at the bottom of chat, scroll chat to new message.

I use the difference between the Y coordinate of the first item div and the Y coordinate of the selected item div. Here is the JavaScript/JQuery code and the html:

function scrollTo(event){
        // In my proof of concept, I had a few <button>s with value 
        // attributes containing strings with id selector expressions
        // like "#item1".
        let selectItem = $($(event.target).attr('value'));
        let selectedDivTop = selectItem.offset().top;

        let scrollingDiv = selectItem.parent();

        let firstItem = scrollingDiv.children('div').first();
        let firstItemTop = firstItem.offset().top;

        let newScrollValue = selectedDivTop - firstItemTop;
        scrollingDiv.scrollTop(newScrollValue);
    }
<div id="scrolling" style="height: 2rem; overflow-y: scroll">
  <div id="item1">One</div>
  <div id="item2">Two</div>
  <div id="item3">Three</div>
  <div id="item4">Four</div>
  <div id="item5">Five</div>
</div>

If this is being done for scrolling to the bottom of chat window, do the following

The idea of scrolling to a particular div in the chat was the following

1) Each chat div consisting of Person, time and message is run in a for loop with class chatContentbox

2) querySelectorAll finds all such arrays. It could be 400 nodes (400 chats)

3) go to the last one

4) scrollIntoView()

let lastChatBox = document.querySelectorAll('.chatContentBox'); 
lastChatBox = lastChatBox[lastChatBox.length-1]; 
lastChatBox.scrollIntoView(); 

use :

var element= $('element');
var maxScrollTop = element[0].scrollHeight - element.outerHeight();
element.scrollTop(maxScrollTop);

or check scroll to bottom :

    var element = $(element);
    var maxScrollTop = element[0].scrollHeight - element.outerHeight();
    element.on('scroll', function() {
        if ( element.scrollTop() >= maxScrollTop ) {
            alert('scroll to bottom');
        }
    });

Sometimes the most simple is the best solution: I do not know if this will help, it helped me to scroll it were ever I wanted too. The higher the "y=" is,the more down it scrolls and of course "0" means top, so there for example "1000" could be bottom, or "2000" or "3000" and so on, depending how long your page is. This usually works in a button with onclick or onmouseover.

window.scrollTo(x=0,y=150);

Set the distance from the top of the scrollable element to be the total height of the element.

const element = this.shadowRoot.getElementById('my-scrollable-div')
element.scrollTop = element.scrollHeight
Related