6

I have a scrollTo function on my page where when you click on a specific button you scroll to a section with a unique ID.

The problem is I am using lazy loading for the images on my website so, this will cause the ScrollTo to stop halfway through the page because of the images which are lazy-loaded.

After all, images are loaded and I click again on the button it works just fine.

My lazy load code:

(() => {
    const runLazy = () => {
        let images = [...document.querySelectorAll('[data-lazy]')];

        const settings = {
            rootMargin: '0px',
            threshold: 0.02
        };

        let observer = new IntersectionObserver((imageEntites) => {
            imageEntites.forEach((image) => {
                if (image.isIntersecting) {
                    observer.unobserve(image.target);
                    image.target.src = image.target.dataset.lazy;
                    image.target.onload = () =>
                        image.target.classList.add('loaded');
                }
            });
        }, settings);

        images.forEach((image) => observer.observe(image));
    };

    runLazy();

})();

My scroll to code:

(() => {
    document.querySelectorAll('a[href^="#"]').forEach((elem) => {
        elem.addEventListener('click', (e) => {
            e.preventDefault();
            let block = document.querySelector(elem.getAttribute('href')),
                offset = elem.dataset.offset
                    ? parseInt(elem.dataset.offset)
                    : 0,
                bodyOffset = document.body.getBoundingClientRect().top;
            window.scrollTo({
                top: block.getBoundingClientRect().top - bodyOffset + offset,
                behavior: 'smooth'
            });
        });
    });
})();

Is there a way to fix this?

Galanthus
  • 1,958
  • 3
  • 14
  • 35
  • Do the images loading in change the height of the page? If you can prefill the space that the images will take up with a placeholder of the same size, then the images loading should have no effect on the scroll. – DBS Jul 21 '21 at 10:05

2 Answers2

2

This seems to be caused by the image size change event during lazy loading.

So you could just set fixed height and width to the lazy load images, to skip this issue.

Edit:

Since fixed image size is not suitable, you can fix this with location.href = '#your-image-tag', plus window.scrollBy in image.onload event.

key code:

(() => {
  document.querySelectorAll('a[href^="#"]').forEach((elem) => {
      elem.addEventListener('click', (e) => {
          e.preventDefault();
          location.href = elem.getAttribute('href')
      });
  });
})()
image.target.onload = () => {
  image.target.classList.add("loaded");

  // TODO: check current image below or upper the target image
  window.scrollBy(0, image.target.clientHeight)
  // or window.scrollBy(0, 0 - image.target.clientHeight)
}

live demo: https://codesandbox.io/s/focused-field-2q3py?file=/src/index.js

banyudu
  • 1,046
  • 9
  • 19
  • I am setting images 100% H and W. Setting it to fixed is not the thing I want to. So, there is no other way to do right? – Galanthus Jul 21 '21 at 10:09
  • @Galanthus I think 100% is not fixed size, `100px` is. It's an interesting question, I will try in a codesandbox and update this answer later. – banyudu Jul 21 '21 at 10:13
  • The reason why I am not setting it to fixed width and height is that I have images on different pages all over the place with the same code. When I set it to a fixed w x h layout would look funky. Never knew that It will conflict – Galanthus Jul 21 '21 at 10:15
  • also forgot to mention that if you face dynamic images like from WordPress clients can upload vertical, horizontal larger, smaller images.. and setting fixes height will kill the website layout. – Galanthus Jul 21 '21 at 10:30
  • @Galanthus updated my answer with a new solution – banyudu Jul 22 '21 at 03:31
0

I tried any solutions, but this is better for me:

element.scrollIntoView({
     block: 'start',
     behavior: "smooth"
});
  • 2
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Yunnosch May 30 '22 at 06:12