【问题标题】:How can I make Chrome scroll to a section including an auto scrolling div?如何让 Chrome 滚动到包含自动滚动 div 的部分?
【发布时间】:2021-04-04 19:16:14
【问题描述】:

我需要一个纯 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 属性?

【问题讨论】:

  • 你预计会发生什么?
  • 我认为点击链接时页面仍会滚动到section2
  • 我认为这是 HTML 结构的问题。看看我的回答。

标签: javascript html google-chrome scroll


【解决方案1】:

以下答案仅对 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 毫秒,您会注意到,当自动滚动未运行时,锚滚动工作正常,但如果在滚动动画期间触发自动滚动,则会中断。

我发现的解决方法是在窗口滚动时停止自动滚动,但可能有一些方法可以异步滚动多个元素。

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>

【讨论】:

  • 您使用的是哪个浏览器?这在 Chrome 中对我不起作用。就像在我的第二个示例中一样,根本没有发生滚动。 @edit 似乎在 Firefox 中运行良好
  • 是的,我使用的是 Firefox。似乎确实是Chrome的问题。 Edge 也有这种行为,所以它可能与 Chromium 有关。
  • @DreiDe 显然 Chrome 中的同时滚动存在问题。
  • 是的,好像是个bug:stackoverflow.com/questions/49318497/…
【解决方案2】:

终于想出了一个解决办法。它涉及通过 jQuery 手动滚动页面,类似于此处提供的答案:Anchor <a> tags not working in chrome when using #

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多