Laterneman
Laterneman

Reputation: 297

Vue js scrollIntoView in only the element's div

I have a vue page with two divs. The Select-Div has a list of elements. If I click on an element from the list the Scroll-Div should scroll to the corresponding id element inside (preferably to the center of that element) which has the long description of the list element's details.

The problem that I'm having is that if I use scrollIntoView then the whole page is scrolling into the center also - so both the Scroll-Div is scrolling into its place but also the main page's scroll too.

Also note: inside the Scroll-Div there is a recursive component so I can only use ids and not refs.

My goTo() function on the main page:

    goTo(id) {
      const element = document.getElementById(`Id-${id}`);

      if (element) {
         element.scrollIntoView({
           block: "center",
           behavior: "smooth",
         });
      }
    },

This gets the emited id from the Select-Div and selects the corresponding html id from the Scroll-Div.

enter image description here

Upvotes: 1

Views: 1951

Answers (1)

Kunukn
Kunukn

Reputation: 2236

It seems like scrollBy is a good API for this.

https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy

A code example in Vue 2 could look like this

<template>
  <div class="select-component">
    <div class="container">
      <div class="scroll-div" ref="scrollDiv">
        <p id="a">A lorem ipsum</p>
        <p id="b">B lorem ipsum</p>
        <p id="c">C lorem ipsum</p>
      </div>

      <div class="select-div">
        <button @click="goto('a')">Goto a</button>
        <button @click="goto('b')">Goto b</button>
        <button @click="goto('c')">Goto c</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    goto(id) {
      let scrollDiv = this.$refs.scrollDiv;
      let el = scrollDiv.querySelector(`#${id}`);

      if (el) {
        let scrollDivRect = scrollDiv.getBoundingClientRect();
        let idRect = el.getBoundingClientRect();

        let y = scrollDivRect.y;
        let y1 = idRect.y;

        let offset = y1 - y;

        scrollDiv.scrollBy({
          top: offset,
          behavior: "smooth",
        });
      }
    },
  },
};
</script>

Demo

https://codesandbox.io/s/vue-scroll-to-item-on-click-for-scrollable-container-9s7xi?file=/src/components/SelectComponent.vue

Upvotes: 2

Related Questions