0

Background

I am working on creating a single page website. It is almost complete and works amazingly! But there was 1 bug I could never manage to fix. When a supported anchor (links to a section) is clicked, rather then reloading the page, I would scroll to that section.

If the section is already loaded, it scrolls to it normally. enter image description here

If it is not loaded, the request is queued for later. This is when the bug occurs. enter image description here Rather then scrolling to Home, it scrolls just below it. If Portfolio is requested, it scrolls halfway up.

Steps to reproduce

Assuming I continue to work on this design, it can be viewed on my website: https://cjloewen.ca/.

  1. Refresh the page. For testing purposes, sections won't load for 10 seconds.
  2. While loading, any section can be requested. If that section is not currently loaded, a loading icon will display next to the link.
  3. Once a requested section is loaded, loading will halt, it will wait for the user to stop scrolling then it will scroll to the requested section using elem.scrollIntoView({ behavior: 'smooth', block: 'start' });.

What I tried

  • I have verified it is scrolling to the correct element and no other elements afterword.
  • I switched to using an MutationObserver to know when the element is added to the DOM.
  • I tried waiting for requestAnimationFrame before scrolling.
  • I tried adding a short 500 millisecond timeout before scrolling.
  • I have tried adding a 60 second timeout before scrolling, making sure I am not interacting with the page at any point.
  • I tried scrolling using scrollTo instead of scrollIntoView (same behavior).
  • I tried it in Edge (slightly different behavior but same problem).

Source code

All relevant source code can be found at https://cjloewen.ca/js/main.js (source map included).

  • I insert sections on line 156.
previous.before(next)
previous.after(next)
  • I lock loading on line 80.
// Set the lock.
mainContentLockWaiting = [];
mainContentLock = true;
// ...
// Reset the lock.
mainContentLock = false;
for (let insert of mainContentLockWaiting)
    insert();
  • I wait for the user to stop scrolling on line 84.
let isScrolling = null;
let scrollListener = function() {
    clearTimeout(isScrolling);
    isScrolling = setTimeout(function() {
        mainContent.removeEventListener('scroll', scrollListener);
        resolve();
    }, 250);
}
mainContent.addEventListener('scroll', scrollListener, false);
  • scrollIntoView is called on line 73.
elem.scrollIntoView({ behavior: 'smooth', block: 'start' });

Any help is greatly appreciated!

cj-
  • 167
  • 1
  • 12
  • 1
    If you want solutions here, you will need to provide code. External links to code dont count because they can become broken links. – GetSet Sep 03 '20 at 22:43
  • If you serve static content, you can define the height of the "replaced elements" that will hold your deferred medias (e.g, set the CSS height of the element which will hold your videos to the actual height they will have when the video is loaded). – Kaiido Sep 04 '20 at 01:24
  • @Kaiido Just checked, I am setting the heights explicitly on the images and video and made sure they are using it before it loads (section sizes are not changing while scrolling). – cj- Sep 04 '20 at 01:54

0 Answers0