Scroll to bottom of div with Vue.js

Javascriptvue.js

Javascript Problem Overview


I have a Vue component with several elements in it. I want to automatically scroll to the bottom of that element when a method in the component is called.

Basically, do the same as this. However, I haven't found a way to get the element within my component and modify scrollTop

I'm currently using Vue 2.0.8

Javascript Solutions


Solution 1 - Javascript

As I understand, the desired effect you want is to scroll to the end of a list (or scrollable div) when something happens (e.g.: an item is added to the list). If so, you can scroll to the end of a container element (or even the page it self) using only pure JavaScript and the VueJS selectors.

var container = this.$el.querySelector("#container");
container.scrollTop = container.scrollHeight;

I've provided a working example in this fiddle.

Every time a item is added to the list, the list is scrolled to the end to show the new item.

Hope this helps you.

Solution 2 - Javascript

2022 easy, readable, smooth scrolling ability, & won't hurt your brain... use el.scrollIntoView()

scrollIntoView() has options you can pass it like scrollIntoView({behavior: 'smooth'}) to get smooth scrolling out of the box and does not require any external libraries.

Here is a fiddle.

methods: {
  scrollToElement() {
    const el = this.$refs.scrollToMe;

    if (el) {
      // Use el.scrollIntoView() to instantly scroll to the element
      el.scrollIntoView({behavior: 'smooth'});
    }
  }
}

Then if you wanted to scroll to this element on page load you could call this method like this:

mounted() {
  this.scrollToElement();
}

Else if you wanted to scroll to it on a button click or some other action you could call it the same way:

<button @click="scrollToElement">scroll to me</button>

The scroll works all the way down to IE 8. The smooth scroll effect does not work out of the box in IE or Safari. If needed there is a polyfill available for this here as @mostafaznv mentioned in the comments.

Solution 3 - Javascript

I tried the accepted solution and it didn't work for me. I use the browser debugger and found out the actual height that should be used is the clientHeight BUT you have to put this into the updated() hook for the whole solution to work.

data(){
return {
  conversation: [
    {
    }
  ]
 },
mounted(){
 EventBus.$on('msg-ctr--push-msg-in-conversation', textMsg => {
  this.conversation.push(textMsg)
  // Didn't work doing scroll here
 })
},
updated(){              <=== PUT IT HERE !!
  var elem = this.$el
  elem.scrollTop = elem.clientHeight;
},

Solution 4 - Javascript

  1. Use the ref attribute on the DOM element for reference
<div class="content scrollable" ref="msgContainer">
    <!-- content -->
</div>
  1. You need to setup a WATCH
  data() {
    return {
      count: 5
    };
  },
  watch: {
    count: function() {
      this.$nextTick(function() {
        var container = this.$refs.msgContainer;
        container.scrollTop = container.scrollHeight + 120;
      });
    }
  }
  1. Ensure you're using proper CSS
.scrollable {
  overflow: hidden;
  overflow-y: scroll;
  height: calc(100vh - 20px);
}

Solution 5 - Javascript

Here is a simple example using ref to scroll to the bottom of a div.

/*
Defined somewhere:
  var vueContent = new Vue({
      el: '#vue-content',
      ...

*/

var messageDisplay = vueContent.$refs.messageDisplay;
messageDisplay.scrollTop = messageDisplay.scrollHeight;

<div id='vue-content'>
  <div ref='messageDisplay' id='messages'>
    <div v-for="message in messages">
      {{ message }}
    </div>
  </div>
</div>

Notice that by putting ref='messageDisplay' in the HTML, you have access to the element through vueContent.$refs.messageDisplay

Solution 6 - Javascript

If you need to support IE11 and (old) Edge, you can use:

scrollToBottom() {
	let element = document.getElementById("yourID");
	element.scrollIntoView(false);
}

If you don't need to support IE11, the following will work (clearer code):

scrollToBottom() {
	let element = document.getElementById("yourID");
	element.scrollIntoView({behavior: "smooth", block: "end"});
}

Solution 7 - Javascript

In the related question you posted, we already have a way to achieve that in plain javascript, so we only need to get the js reference to the dom node we want to scroll.

The ref attribute can be used to declare reference to html elements to make them available in vue's component methods.

Or, if the method in the component is a handler for some UI event, and the target is related to the div you want to scroll in space, you can simply pass in the event object along with your wanted arguments, and do the scroll like scroll(event.target.nextSibling).

Solution 8 - Javascript

Try vue-chat-scroll:

Install via npm: npm install --save vue-chat-scroll

Import:

import Vue from 'vue'
import VueChatScroll from 'vue-chat-scroll'
Vue.use(VueChatScroll)

in app.js after window.Vue = require('vue').default;

then use it with

:

<ul class="messages" v-chat-scroll>
  // your message/chat code...
</ul>

Solution 9 - Javascript

I had the same need in my app (with complex nested components structure) and I unfortunately did not succeed to make it work.

Finally I used vue-scrollto that works fine !

Solution 10 - Javascript

The solution did not work for me but the following code works for me. I am working on dynamic items with class of message-box.

scrollToEnd() {
            setTimeout(() => {
                this.$el
                    .getElementsByClassName("message-box")
                    [
                        this.$el.getElementsByClassName("message-box").length -
                            1
                    ].scrollIntoView();
            }, 50);
        }

Remember to put the method in mounted() not created() and add class message-box to the dynamic item.

setTimeout() is essential for this to work. You can refer to https://forum.vuejs.org/t/getelementsbyclassname-and-htmlcollection-within-a-watcher/26478 for more information about this.

Solution 11 - Javascript

For those that haven't found a working solution above, I believe I have a working one. My specific use case was that I wanted to scroll to the bottom of a specific div - in my case a chatbox - whenever a new message was added to the array.

const container = this.$el.querySelector('#messagesCardContent');
        this.$nextTick(() => {
          // DOM updated
          container.scrollTop = container.scrollHeight;
        });

I have to use nextTick as we need to wait for the dom to update from the data change before doing the scroll!

I just put the above code in a watcher for the messages array, like so:

messages: {
      handler() {
        // this scrolls the messages to the bottom on loading data
        const container = this.$el.querySelector('#messagesCard');
        this.$nextTick(() => {
          // DOM updated
          container.scrollTop = container.scrollHeight;
        });
      },
      deep: true,
    }, 

Solution 12 - Javascript

This is what worked for me

this.$nextTick(() => {
   let scrollHeight = this.$refs.messages.scrollHeight
   window.scrollTo(0, scrollHeight)
})

Solution 13 - Javascript

My solutions without modules:

Template

<div class="scrollable-content" ref="conversations" />

Script

scrollToBottom() {
  const container = this.$refs.conversations;
  container.scrollTop = container.scrollHeight;
},

Solution 14 - Javascript

scrollToBottom() {
    this.$nextTick(function () {
        let BoxEl = document.querySelector('#Box');
        if(BoxEl)
            BoxEl.scrollTop = BoxEl.scrollHeight;
    });
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionangrykoalaView Question on Stackoverflow
Solution 1 - JavascriptItalo AyresView Answer on Stackoverflow
Solution 2 - JavascriptmaxshutyView Answer on Stackoverflow
Solution 3 - JavascriptjuliangonzalezView Answer on Stackoverflow
Solution 4 - JavascriptAlpesh PatilView Answer on Stackoverflow
Solution 5 - JavascriptcapncanuckView Answer on Stackoverflow
Solution 6 - JavascriptKatinka HesselinkView Answer on Stackoverflow
Solution 7 - JavascriptJJPandariView Answer on Stackoverflow
Solution 8 - JavascriptDaljit SinghView Answer on Stackoverflow
Solution 9 - JavascriptOusmaneView Answer on Stackoverflow
Solution 10 - Javascriptgerald hengView Answer on Stackoverflow
Solution 11 - JavascriptLurein PereraView Answer on Stackoverflow
Solution 12 - JavascriptTimothyView Answer on Stackoverflow
Solution 13 - JavascriptQuang DongView Answer on Stackoverflow
Solution 14 - JavascriptDeepak Kr BansalView Answer on Stackoverflow