Search code examples
htmlcssvue.jsbootstrap-vue

Scrolling to the bottom of a div is not working


I'm trying to scroll a div to their bottom when some button is clicked (chat context) but it's not working properly

In this chat i need to show the message at the top on start and when i get more content scroll automatically to the bottom showing the most recent messages, I already tried scrollIntoView as in the following code:

      const element = this.$el.querySelector(".chat-box");
      element.scrollIntoView({behavior: "smooth", block: "end"})
    }

I expect to scroll to end of the div, but actually scrolling near to the bottom, missing some content. Only scrollIntoView actually move the scroll, i tried element.scrollTop = element.scrollHeigh and nothing happens


Solution

  • I assume you are pushing the new message in the same callback as the scrollInToView call?

    Here what I think you are doing:

    this.messages.push(newMessage);
    const element = this.$el.querySelector(".chat-box");
    element.scrollIntoView({behavior: "smooth", block: "end"})
    

    To quote from the Vue.js docs:

    In case you haven’t noticed yet, Vue performs DOM updates asynchronously. Whenever a data change is observed, it will open a queue and buffer all the data changes that happen in the same event loop. If the same watcher is triggered multiple times, it will be pushed into the queue only once. This buffered de-duplication is important in avoiding unnecessary calculations and DOM manipulations. Then, in the next event loop “tick”, Vue flushes the queue and performs the actual (already de-duped) work.

    That means that you need to wait for the next tick before you try to scroll into the last item, so something like this should work:

    this.messages.push(newMessage);
    
    // wait until the new message is rendered
    this.$nextTick(() => {
      // then scroll
      const element = this.$el.querySelector(".chat-box");
      element.scrollIntoView({behavior: "smooth", block: "end"})
    });