0
const imgTargets = document.querySelectorAll('img[data-src]');
 
const loadImg = function (entries, observer) {
  const [entry] = entries;
 
  if (!entry.isIntersecting) return;
 
  // Replace src with data-src
  entry.target.src = entry.target.dataset.src;
 
  entry.target.addEventListener('load', function () {
    entry.target.classList.remove('lazy-img');
  });
 
  observer.unobserve(entry.target);
};
 
const imgObserver = new IntersectionObserver(loadImg, {
  root: null,
  threshold: 0.5,
  // rootMargin: '200px', (comment)
});
 
imgTargets.forEach(img => imgObserver.observe(img));

The codes down below is applying the lazy images effect for images on scroll, so i used the Intersection Observer API.

As you can see, i set the threshold is 50%, that's mean, the viewport should intersect 50% of the image height to make the callback executed.

But, when i scrolled just to reached the very top point of the image, the callback is executed ¯_(ツ)_/¯. You can see at the picture.

You can see the demo of this effect at here, which is the effect that im trying to build on my own, and my HTML and the CSS codes are just the same with this demo website.

The proof of my situations

Pls help me to find out, although the effect is also satisfying but i want to know why this is happening, thank you so much, readers.

And here is my html and css codes that are related to the images and the parent sections: HTML

  <section class="section" id="section--1">
    <div class="section__title">
      <h2 class="section__description">Features</h2>
      <h3 class="section__header">
        Everything you need in a modern bank and more.
      </h3>
    </div>


    <!-- The container of the images and the descriptions -->
    <div class="features">
      <!-- First image --> <img src="img/digital-lazy.jpg" data-src="img/digital.jpg" alt="Computer" class="features__img lazy-img" />
      <div class="features__feature">
        <div class="features__icon">
          <svg>
            <use xlink:href="img/icons.svg#icon-monitor"></use>
          </svg>
        </div>
        <h5 class="features__header">100% digital bank</h5>
        <!-- Descriptions of first image --> <p>
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Unde alias
          sint quos? Accusantium a fugiat porro reiciendis saepe quibusdam
          debitis ducimus.
        </p>
      </div>

      <div class="features__feature">
        <div class="features__icon">
          <svg>
            <use xlink:href="img/icons.svg#icon-trending-up"></use>
          </svg>
        </div>
        <h5 class="features__header">Watch your money grow</h5>
        <!-- The second description of the second image --> <p>
          Nesciunt quos autem dolorum voluptates cum dolores dicta fuga
          inventore ab? Nulla incidunt eius numquam sequi iste pariatur
          quibusdam!
        </p>
      </div>
      <!-- Second image --> <img src="img/grow-lazy.jpg" data-src="img/grow.jpg" alt="Plant" class="features__img lazy-img" />

      <!-- Third image --> <img src="img/card-lazy.jpg" data-src="img/card.jpg" alt="Credit card" class="features__img lazy-img" />
      <div class="features__feature">
        <div class="features__icon">
          <svg>
            <use xlink:href="img/icons.svg#icon-credit-card"></use>
          </svg>
        </div>
        <h5 class="features__header">Free debit card included</h5>
        <!-- The third description of the third image --> <p></p><p>
          Quasi, fugit in cumque cupiditate reprehenderit debitis animi enim
          eveniet consequatur odit quam quos possimus assumenda dicta fuga
          inventore ab.
        </p>
      </div>
    </div>


  </section>

And here is the css:

/* Should notice*/

.features {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  margin: 0 12rem;
}

.features__img {
  width: 100%;
}

.lazy-img {
  filter: blur(20px);
}

.features__feature {
  align-self: center;
  justify-self: center;
  width: 70%;
  font-size: 1.5rem;
}

/* The styles i think its not important but related to the feature section*/
.features__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-primary-opacity);
  height: 5.5rem;
  width: 5.5rem;
  border-radius: 50%;
  margin-bottom: 2rem;
}

.features__icon svg {
  height: 2.5rem;
  width: 2.5rem;
  fill: var(--color-primary);
}

.features__header {
  font-size: 2rem;
  margin-bottom: 1rem;
}

Please, if you need some more informations, please call me to give, i will always ready to provide, thank you so much.

The images are here The images have the name which is contains -lazy are the images that are have the low numebrs of pixels, that i use the first before, and then add the class of the blur filters, and the, when the users scroll to the images, they will change to the orginal ones and remove the blur filers.

Gia Phu Tang
  • 101
  • 6
  • Perhaps you could create a snipppet or a jsfiddle to illustrate this effect "live"? – Professor Abronsius Apr 18 '21 at 06:33
  • Please could you show us the HTML and any relevant CSS that defines the img elements? – A Haworth Apr 18 '21 at 07:06
  • I think what is happening perhaps ( hard to know 100% without HTML and CSS ) is likely that the `img` elements occupy no space when they do not have a `src` attribute for even if you set the `threshold:1.0` the callback will fire immediately that `img` enters the viewport. If you set the `img` width and heights explicitly you might find a different effect. – Professor Abronsius Apr 18 '21 at 07:20
  • i have added html and css codes, thank you so much. – Gia Phu Tang Apr 18 '21 at 07:30

1 Answers1

0

Before an img is loaded the system does not have any height for it. Therefore the img element which you are observing triggers the observed 'isIntersecting' immediately it comes into the bottom of the viewport because 50% of nothing is nothing.

I don't know exactly what you want to do but here is a snippet where an invented height is added to a div wrapping an img element and when 50% of this is showing in the viewport, the img gets loaded.

Possibly you could find out the heights of each image before they are loaded and use this technique to put in the proper heights, but it looks a bit odd an image suddenly appearing when there has been a blank space at the bottom of the page.

const imgTargets = document.querySelectorAll('div.imgwrapper');
 
const loadImg = function (entries, observer) {
  const [entry] = entries;
 
  if (!entry.isIntersecting) return;
 
  // Replace src with data-src
  entry.target.firstElementChild.src = entry.target.firstElementChild.dataset.src;
 
  entry.target.addEventListener('load', function () {
    entry.target.classList.remove('lazy-img');
  });
 
  observer.unobserve(entry.target);
};
 
const imgObserver = new IntersectionObserver(loadImg, {
  root: null,
  threshold: 0.5,
  // rootMargin: '200px', (comment)
});
 
imgTargets.forEach(img => imgObserver.observe(img));
.talldiv {
  background: linear-gradient(cyan,lime);
  height: 150vh;
}
.imgwrapper {
  height: 200vh;
  background-color: pink;
}
<div class="talldiv">SCROLL DOWN</div>
<div class="imgwrapper"><img src="" data-src="https://picsum.photos/id/1015/200/300.jpg" />
</div>
A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • Dear A Haworth, Thank you so much for the answer, but i still have some questions want you to make it clear. So what you mean, is that this problem happens because the images doesn't have height, right? So we need to fix that using a container that have a height, so then when the user scrolled to 50% of that container element's height, the callback will do something with the images, right? By the way, what i want to do is remove the blur filters for the images when the user scrolled to 50% of the images. – Gia Phu Tang Apr 18 '21 at 07:51
  • Yes, that's right. But now I'm not sure what you want to do exactly. If they are loaded (albeit blurred) already then there shouldn't be a problem as they will have height and you can just remove the blur when they are 50% in view. I'll look at your HTML. – A Haworth Apr 18 '21 at 07:57
  • Could you put some img srcs up that we can use - e.g. load them into the imgur system or give a complete url to your images. Making a complete snippet would be very helpful. – A Haworth Apr 18 '21 at 08:01
  • ok wait me a bit, sorry for a long repping time – Gia Phu Tang Apr 18 '21 at 11:25
  • Do you think there are some other reasons that this problem happens? – Gia Phu Tang Apr 19 '21 at 10:12
  • I can’t see there is any other problem but without being able to see your actual images I can’t tell for sure. For example, how do the dimensions compare. Are you able to put full image urls in your question. – A Haworth Apr 20 '21 at 07:33
  • i have added, check it out, thank you so much my friend. – Gia Phu Tang Apr 20 '21 at 11:06