Guide to autonomously scrolling exclusively within the <div> element in Vue.js

I am currently developing a frontend application using Vue 2.

Within the application, I have implemented a chat feature and enabled auto-scroll to the end of the chat on update().

An issue has arisen where the scroll action affects not only the chat box but also scrolls the entire page to that specific moment. Is there a way to override this behavior? (I will display the full code below so you can see that having a reference solely on the last message without referencing the div is not feasible - loaded_messages comes from an API array and dialogs are from WebSocket)

<template>
          <div class="box col-md-8">
            <div id="chat-messages" class="chat__order" style="border: 1px solid grey; overflow-y: scroll;">

                    <ol class="chat">

                  <div v-for="m in loaded_messages[0]"
                        direction="column"
                        justify-content="start"
                        align-items="end"
                        margin-left=2px
                        :key="m.id">
                   <li class="self" v-if="m.username == user"> 
                    <b-avatar :src="m.get_message_info.get_thumbnail"></b-avatar>
                      <div class="msg">

                      <p>{{m.content}}</p>
                      <time>{{m.get_datetime}}</time>

                      </div>
                    </li>

                   <li class="other" v-else> 
                    <b-avatar :src="m.get_message_info.get_thumbnail"></b-avatar>
                        <div class="msg">
                        <p>{{m.content}}</p>
                        <time>{{m.get_datetime}}</time>
                        </div>
                  </li>

                  </div>

                <div  v-for="dialog in dialogs"
                        direction="column"
                        justify-content="start"
                        align-items="end"
                        :key="dialog.id">

                   <li class="self" v-if="dialog.username == user"> 
                    <b-avatar></b-avatar>
                      <div class="msg">
                              <p>{{dialog.message}}</p>
                              <time>{{dialog.datetime}}</time>
                      </div>
                    </li>

                   <li v-else> 
                    <b-avatar></b-avatar>
                    <div class="msg">
                            <p>{{dialog.message}}</p>
                    </div>
                  </li>

                </div> 

                  <div ref="lastMessage"></div>
              </ol>
          </div>
        </div> 

</template>

<script>

        methods: { 

// Custom function for scrolling to the last message

      scrollToElement() {
      const [el] =  this.$refs.lastMessage;
      if (el) {
        el.scrollIntoView({ behavior: "smooth" });
      }
    },

   },

    updated() {
      this.scrollToElement();
    },

</script>

Answer №1

scrollIntoView method doesn't work for scrolling inside a container; it only functions within the document viewport. To scroll to an element inside a container, you will need to calculate the X distance from the top of the element.

You can utilize the following method:

function scrollParentToChild(parent, child) {
// Find parent's position on the page
  var parentRect = parent.getBoundingClientRect();
  // Determine visible area
  var parentViewableArea = {
    height: parent.clientHeight,
    width: parent.clientWidth
  };

  // Locate child element
  var childRect = child.getBoundingClientRect();
  // Check if child is in view
  var isViewable = (childRect.top >= parentRect.top) && (childRect.bottom <= parentRect.top + parentViewableArea.height);

  // If child is not in view, scroll parent element
  if (!isViewable) {
        // Decide whether to scroll to top or bottom based on smallest adjustment
        const scrollTop = childRect.top - parentRect.top;
        const scrollBot = childRect.bottom - parentRect.bottom;
        if (Math.abs(scrollTop) < Math.abs(scrollBot)) {
            // Near top of list
            parent.scrollTop += scrollTop;
        } else {
            // Near bottom of list
            parent.scrollTop += scrollBot;
        }
  }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered a problem while attempting to create a new Angular project due to an unexpected termination of JSON input during parsing

Angular CLI: 10.0.4 Node: 12.18.3 npm : 6.14.6 Whenever I attempt to start a new angular project, I encounter errors that prevent the process from completing successfully. The installation of packages hangs indefinitely and eventually throws an erro ...

Determining the JavaScript event source within a function's scope: A guide

Query Can we determine the origin of a function being triggered by either a user event or an async event, without having access to the original event parameter? Situation I am faced with the challenge of identifying the event source within a nested funct ...

Can the transition of Fade be postponed?

Objective: I am aiming to trigger a Fade transition after a specific amount of time has elapsed (e.g., 4000 milliseconds). Here is an excerpt from my code: <Fade in timeout={{ enter: 8000 }}> <Box display="flex" justifyContent="center"> ...

Attempting to install puppeteer within the Visual Studio Code terminal with financial support

I am having trouble installing puppeteer using the VSC terminal. Every time I try to run the npm install command, it doesn't download and prompts me about funding. Can someone please assist me with this issue? npm i puppeteer up to date, audited 67 p ...

Conceal a division on a webpage according to the URL of the specific

<script> function hideSearchField() { if (/menu/.test(window.location.href)) { document.getElementById('searchfield').style.display = 'none'; } } hideSearchField(); </script> I am trying to accomplish this using Jav ...

With the power of jQuery, easily target and retrieve all label elements within a specified

Currently, I'm working on developing a function that should be executed whenever any of the labels for a particular group of radio buttons are clicked. So, I need a way to reference all the labels in this radio button group. In my search for a soluti ...

How can you use jQuery to display an image when hovering over text?

Looking for a tutorial or script that displays an image when hovering over HTML text with the mouse? ...

Leverage variables from different Vue components and link them together

I'm currently working on two different sections of the website First: Is it acceptable to use one instance within another, particularly with v-model? Are there any drawbacks to this approach? Second: Is there a way to reference each other, such as p ...

Caution: Potential Unresolved Promise Rejection Detected (ID: 21) - Error: Undefined is not a valid object when trying to evaluate 'res.json'

ERROR Getting an Unhandled Promise Rejection (id: 21): TypeError: undefined is not an object (evaluating 'res.json'). Any suggestions on fixing this issue in my code? I've checked the logs for user and loggeduserobj, and they seem to be cor ...

Click a button to switch the visibility of a section in an

Is there a way to create a toggle feature in Angular.JS that will open and close a div when clicked on the same div again? Currently, it opens the div when clicked but I want it to also close the div when clicked again. <a ng-href ng-click="openAccordi ...

Using Promises to Iterate in Node JS

To begin my NodeJS app creation journey, I have implemented the following code snippet to be triggered when an admin adds a new product. While most of the code functions correctly, I'm facing difficulty in rendering the view only after the completion ...

Populating JQuery autocomplete using a PHP array

As a beginner in the world of JavaScript and JQuery, I have been scouring the internet for hours trying to find a solution to my query. My goal is to populate a JQuery autocomplete feature using an array that I have created in PHP. Here is a glimpse of the ...

Extract URL as a parameter for $.getJSON using JavaScript

When attempting to include a URL as a parameter along with several other parameters in my frontend to make a JSON request to my Django backend, I am encountering the familiar 404 error - not found. Django urls.py path: path("updateAssignment/<iD&g ...

Tips for locating the :before element's position with Javascript

I am currently working on an animation where I need to change the color of an element in the center once a small circle touches it. Despite trying to use the position() method, it does not work as intended because I am using a :before for animating the div ...

Incorporate concealed image into HTML

When I perform actions with a couple of images, I encounter delays because the browser needs to load the images. For example, if I use $('body').append(''); everything works smoothly without any delays. However, when I try using style= ...

When I receive a 404 response from the API, I aim to start my observable

How can I trigger my observable initialization when receiving a 404 response from the API? The code snippet below is not working as expected. const urlParams = { email: this.email }; this.voicesProfileObservable$ = this.service.request<any>( AVAI ...

Ways to utilize/extract data from an enumeration

Hello there! I am currently diving into the world of React and Typescript, eager to expand my knowledge. Please bear with me if my explanations are not up to par. In my react app, I have a scenario where I created an enum that I want to utilize in two diff ...

What causes a decrease in speed when a function is called without specifying its owner?

Let's consider the following scenario: var abs = Math.abs; Wouldn't abs(-10) be quicker than Math.abs(-10)? Since abs is called directly. This caught my attention: Math.abs vs custom abs function Update: The same test conducted in Internet ...

Steps to confirm if a route has been passed a prop

Within the GridRow.vue file, I have a function that redirects to a specific route while passing along parameters: redirectWithData () { this.$router.push({ name: 'payment.request', params: { per ...

Tips for sending push notifications to multiple devices via Firebase Cloud Messaging

I was exploring ways to send push messages from my expressJS server to my ionic app and I came across GCM. Using GCM, I could deliver messages by passing a list of tokens like this: sender.send(message, { registrationTokens: deviceTokens }, f ...