admin管理员组

文章数量:1303345

I have two overflowing elements on the page, I would like to call ScrollIntoView at the same time for child elements within both of them.

The following works in Firefox, but not Chrome. Is this a bug?

const button = document.querySelector('button');
const one = document.querySelector('.one');
const two = document.querySelector('.two');

button.addEventListener('click', () => {
    one.scrollIntoView({ block: 'center', behavior: 'smooth' });
    two.scrollIntoView({ block: 'center', behavior: 'smooth' });
});
body {
    text-align: center;
}

#container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    width: 100%;
    height: 130px;
}

#container > div {
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid black;
}

button {
    font-size: 1.5rem;
    margin: 0.5rem auto;
}
<div id="container">
    <div>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1 class="one">Boo!</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
    </div>

    <div>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1 class="two">Boo!</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
    </div>
</div>

<button>click to scroll</button>

I have two overflowing elements on the page, I would like to call ScrollIntoView at the same time for child elements within both of them.

The following works in Firefox, but not Chrome. Is this a bug?

const button = document.querySelector('button');
const one = document.querySelector('.one');
const two = document.querySelector('.two');

button.addEventListener('click', () => {
    one.scrollIntoView({ block: 'center', behavior: 'smooth' });
    two.scrollIntoView({ block: 'center', behavior: 'smooth' });
});
body {
    text-align: center;
}

#container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    width: 100%;
    height: 130px;
}

#container > div {
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid black;
}

button {
    font-size: 1.5rem;
    margin: 0.5rem auto;
}
<div id="container">
    <div>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1 class="one">Boo!</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
    </div>

    <div>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1 class="two">Boo!</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
    </div>
</div>

<button>click to scroll</button>

Share asked Mar 11, 2021 at 16:22 MattMatt 10.4k5 gold badges37 silver badges68 bronze badges 1
  • 1 I gave you the solution using scrollTo(). Do you have any questions or requests? Is there anything that needs to be done in my code? And try to avoid using ScrollIntoView. Since there are disadvantages. For instance - stackoverflow./questions/65953805/… – s.kuznetsov Commented Mar 12, 2021 at 5:10
Add a ment  | 

4 Answers 4

Reset to default 4

Better use the normal scrollTo() scrolling method with smooth scroll.

I had to use a for {}, since I was referring to a collection of scrollable divs inside #container:

const container_div = document.querySelectorAll("#container > div");

Also, I have specified the same class for both <h1> control tags:

const text = document.querySelectorAll(".boo");

const button = document.querySelector("button");
const container_div = document.querySelectorAll("#container > div");
const text = document.querySelectorAll(".boo");

button.addEventListener("click", () => {
    for (i = 0; i < container_div.length; i++) {
        container_div[i].scrollTo({ top: text[i].offsetTop, behavior: "smooth" });
    }
});
body {
    text-align: center;
}

#container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    width: 100%;
    height: 130px;
}

#container > div {
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid black;
}

button {
    font-size: 1.5rem;
    margin: 0.5rem auto;
}
<div id="container">
    <div>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1 class="boo">Boo!</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
    </div>

    <div>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1 class="boo">Boo!</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
        <h1>...</h1>
    </div>
</div>

<button>click to scroll</button>

Seems like Chrome blocks 2 smooths scrolls at the same time. Change behavior into auto and scroll will work.

I solved this issue by setting different timeouts. In my example i had two ponents. Each firing at 500 and 1000 ms.

setTimeout(() => {
  scrollToCard(this.selectedId);
}, this.type === 'first' ? 500 : 1000);

scrollToCard(id: string) {
  const selected = document.getElementById(
    'scrollTo-' + id + '-' + this.type
  );

  if (selected) {
    selected.scrollIntoView({
      behavior: 'smooth',
      block: 'nearest',
      inline: 'start',
    });
  }
}

As the answers suggests above that Chrome blocks 2 smooths scrolls at the same time. I fixed it by only triggering the second scroll after a small timeout of 300ms giving enough time for the first smooth scroll to finish. This was achieved by using setTimeOut.

 setTimeout(() => {
    myRef?.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
  }, 300);

Although this works for my use case, you could also try setting the behaviour: auto for the other scroll for it to work simultaneously.

本文标签: javascriptWhy doesn39t ScrollIntoView work on two simultaneous elementsStack Overflow