如何让 Chrome 滚动到包含自动滚动 div 的部分?

How can I make Chrome scroll to a section including an auto scrolling div?

我需要一个纯粹的 HTML 解决方案来滚动到我页面上的某个部分。我通常这样做:

html {
  scroll-behavior: smooth;
}

#section1 {
  background: blue;
  height: 500px;
}

#section2 {
  background: red;
  height: 500px;
}
<a href="#section2">Section 2</a>
<section id="section1"></section>
<section id="section2"></section>

但是,一旦我在该页面的某处添加自动滚动 div,它就会停止工作。

function scroll() {
  document.getElementById("autoScroll").scrollBy(2, 2);
  setTimeout(scroll, 30);
}
scroll();
html {
  scroll-behavior: smooth;
}

#section1 {
  background: blue;
  height: 500px;
}

#section2 {
  background: red;
  height: 500px;
}

#autoScroll {
  height: 200px;
  overflow-y: scroll;
}

#content {
  height: 500px;
  background: green;
}
<a href="#section2">Section 2</a>
<section id="section1"></section>
<section id="section2">
  <div id="autoScroll">
    <div id="content"></div>
  </div>
</section>

这似乎是 Chrome 唯一的问题。至少它在 Firefox 中运行良好。我是否也需要使用 Javascript scrollIntoView() 在 Chrome 中实现此效果?还是我缺少一些 HTML 属性?

以下答案仅适用于 Firefox

它仍在滚动到第 2 部分,但自动滚动元素 第 2 部分内,某种程度上它覆盖了第 2 部分的开头部分。问题是在 HTML 结构中。

查看:

function scroll() {
  document.getElementById("autoScroll").scrollBy(2, 2);
  setTimeout(scroll, 30);
}
scroll();
html {
  scroll-behavior: smooth;
}

#section1 {
  background: blue;
  height: 500px;
}

#section2 {
  background: red;
  height: 500px;
}

#autoScroll {
  height: 200px;
  overflow-y: scroll;
}

#content {
  height: 500px;
  background: green;
}
<a href="#section2">Section 2</a>
<section id="section1"></section>
<section id="section2"></section>
<section id="section3">
  <div id="autoScroll">
    <div id="content"></div>
  </div>
</section>

Chromium 中的同步滚动似乎存在问题。

如果将延迟从 30 毫秒增加到 1000 毫秒,您会注意到虽然没有自动滚动 运行,但锚点滚动工作得很好,但如果在滚动期间触发自动滚动,它会被打断动画。

我找到的解决方法是在 window 滚动时停止自动滚动,但可能有一些方法可以让多个元素异步滚动。

let canScroll = true;

async function scroll() {
  if(canScroll) {
    document.getElementById("autoScroll").scrollBy(2, 2);
    setTimeout(scroll, 30);
  }
}
scroll();

document.querySelectorAll('a').forEach(el => el.addEventListener('click', scrollHandler));

async function scrollHandler(e) {
  let href = e.target.getAttribute('href');
  
  if(href.startsWith('#')) {
    canScroll = false;
    document.querySelector(href).scrollIntoView();
    setTimeout(() => {
      canScroll = true;
      scroll();
    }, 500);
  }
}
html {
  scroll-behavior: smooth;
}

#section1 {
  background: blue;
  height: 500px;
}

#section2 {
  background: red;
  height: 500px;
}

#autoScroll {
  height: 200px;
  overflow-y: scroll;
}

#content {
  height: 500px;
  background: green;
}
<a href="#section2">Section 2</a>
<a href="https://google.com">Google</a>
<section id="section1"></section>
<section id="section2"></section>
<section id="section3">
  <div id="autoScroll">
    <div id="content"></div>
  </div>
</section>

终于想到了解决办法。它涉及通过 jQuery 手动滚动页面,类似于此处提供的答案:

$(function() {
    $(window).on('hashchange', function () {
        let target = $(location.hash);
        if (target.length) {
            $('body')[0].scrollTop = target.offset().top;
        }
    });
    setTimeout(function () {$(window).trigger('hashchange')}, 150);
});

我不知道为什么需要超时,但忽略它会导致页面在初始加载时根本不滚动。