最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why doesn't `ScrollIntoView` work on two simultaneous elements? - Stack Overflow

programmeradmin1浏览0评论

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.

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>