Observe last child by using intersection observer

I want to apply position fixed when the first section comes in middle and scroll starts and when the last section come in middle the position of .BG changes to relative, so it cannot affect the other divs of the web page.
Is there a way to observe last child and apply position relative to BG.

  const bgEl = document.querySelector(".BG");
      const bgEl2 = document.querySelector(".section");
      function createObserver(el) {
        let observer;
        let options = {
          root: null,
          rootMargin: "0px",
        };

        function handleIntersect(entries, observer) {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              const url = entry.target.getAttribute("BGurl");
              bgEl.style.backgroundImage = `url(${url})`;
              bgEl.style.position = "fixed";
            }
          });
        }

        observer = new IntersectionObserver(handleIntersect, options);
        observer.observe(el);
        return observer;
      }

      (function () {
        const sections = document.querySelectorAll(".main .section");
        const observers = Array.from(sections).map(function (section) {
          createObserver(section);
        });
      })();

It’s a bit hard to find out what you want from your description and that code. Do you maybe have a website where we can see things in action, or could you maybe create a JSFiddle?

1 Like

BTW you don’t need to create a new observer for each element, one can observe many… so maybe something like this?

function handleIntersection (entries, observer) {
  entries.forEach(entry => {
    if (entry.target === observer.root.lastElementChild) {
      // do something
    }
  })
}

const root = document.querySelector('.main')

const observer = new IntersectionObserver(
  handleIntersection, { root })

Array.from(root.children).forEach(child => {
  observer.observe(child)
})

But yeah a fiddle would be helpful. :-)

2 Likes

It sounds like you just want to fix the background image rather than fix the content itself (unless your bg is just a container for the background image) ?

This old codepen shows a method for fixing a number of images and will work in ios (as background-attachment:fixed is buggy in ios).

Is that the sort of thing you were looking for ?

3 Likes

Yes sure here is the link to fiddle:

1 Like

Actually, I want to fix the BG so that all the sections scrolls on it and the background image will change according to each section that’s why i used the observers.If the last section and the first section comes in middle the position of BG changes to relative other fixed. I have another divs in the web page too. That’s why i want to give positions according to the first and last section

Yes i want like this

If I understand correctly then you can do that without js for desktops just by using background-attachment fixed on the image.

Here is your code without the JS.

I changed some of the css as it made incorrect assumptions but I left your html in place although I would not use all the divs that you have and inline styles etc.

Note that the images you are using are not suitable for a full viewport width image as they have to be scaled much too large to cover the viewport. Mosts viewports are landscape so instead of using a portrait image that is 370x 800px you would want a landscape image instead (e.g. 800x 370). However that is too small for a large viewport and quality will suffer. You need to make an image that is about 1500px x 800px and then it can scale up and down without too much loss of quality.

Your 360x 800px is actually 647k anyway which is much to big a file size. You should be able to make an image at the size I suggested at much less than that file size if you optimise properly.

Background-attachment fixe combined width background-size cover does not work well on mobiles and they stretch the image over the whole document. It may be better for smaller screens just to lose the fixed attachment.

If you want full ios support then my original demo above has all the code you need in place. Or you can reinstate your observer code but just do it for touch devices as in my example. No need to bother desktop with the js unless of course you are adding some other fancy transitions.

Hope that helps with your project.

2 Likes

Sure, all I was saying is that you only need a single observer, not one for each observed element. But as @PaulOB just demonstrated you might not even need that. ^^

1 Like

I converted the last pen to use the Intersection observer instead of background-attachment fixed.

In your original you were just changing the background of a single BG image div. This means the image changed abruptly and you were getting a blank screen on the changes. Therefore I gave each image its own container and then it can fade in and out smoothly for a better experience.

I also changed the images to show how they should look.

That version should work on mobiles although I haven’t checked :slight_smile:

2 Likes

It’s a slow day and I’m playing. :slight_smile:

Here’s a slightly different version that works on desktop and ios without any JS at all.

I think that covers all bases now :slight_smile:

1 Like