0

I need a pure HTML solution to scroll to a section on my page. I usually do it like this:

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>

However this stops working as soon as I add an auto-scrolling div somewhere on that page.

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>

This seems to be an Chrome only problem. At least it works fine in Firefox. Do I need to use Javascript scrollIntoView() to achieve this effect in Chrome too? Or am I missing some HTML attributes?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
DreiDe
  • 109
  • 1
  • 10

2 Answers2

0

The answer below is only valid for Firefox

It still is scrolling to section 2, but the auto-scroll element is inside section 2, in a way that it covers the beginning part of section 2. The problem was in the HTML structure.

Check it out:

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>

There seems to be an issue with simultaneous scrolls in Chromium.

If you increase the delay from 30ms to 1000ms you will notice that while the auto-scroll is not running, the anchor scroll works just fine, but it gets interrupted if the auto scroll fires during the scroll animation.

The workaround I have found involves stopping the auto scroll while the window is scrolling, but there is probably some way to have asynchronous scrolling of multiple elements.

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>
Set
  • 183
  • 9
  • Which browser are you using? This doesn't work for me in Chrome. Like in my second example no scroll is happening **at all**. @edit seems to work fine in Firefox though – DreiDe Dec 27 '20 at 23:58
  • Yeah, I'm using Firefox. Seems to be a problem with Chrome indeed. Edge also got this behavior, so it's probably something with Chromium. – Set Dec 28 '20 at 00:16
  • @DreiDe Apparently there is an issue with simultaneous scrolls in Chrome. – Set Dec 28 '20 at 00:35
  • Yes, seems to be a bug: https://stackoverflow.com/questions/49318497/google-chrome-simultaneously-smooth-scrollintoview-with-more-elements-doesn – DreiDe Dec 28 '20 at 10:43
0

In finally came up with a solution. It involves scrolling the page manually via jQuery similar to the answer provided here: 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);
});

I don't know why exactly the timeout is required, but leaving it out results in the page not scrolling at all on initial load.

DreiDe
  • 109
  • 1
  • 10