0

I am trying to change the burger menu on my website everytime it sits on top of a section with a light background for visibility. I tried to use intersection observer, and the solution seems working, however it triggers too early on scroll, before actually the section intersects with the menu.

I am new to intersection observer, I tried to find something useful online but with no much luck.

    const body = document.querySelector('body')
    const sections = body.querySelectorAll('.change-menu')
    const options = {
        root: null,
        threshold: 0,
        rootMargin:'-40px 0px -80% 0px'
    }


    const observer = new IntersectionObserver((entries,observer) => {
            entries.forEach(entry => {
                if(entry.isIntersecting) {
                document.querySelectorAll('.menu-item').forEach(bar => {
                    body.classList.add('black')
                })
            } else {
                document.querySelectorAll('.menu-item').forEach(bar => {
                    body.classList.remove('black')
                })
            }
            })

    }, options)



    sections.forEach(section => {
      observer.observe(section)
    })

Here is a jsfiddle of an example of my problem:

https://jsfiddle.net/bc7w8zt1/

Anyone can shed some light on it please?

1 Answers1

0

I think the JSFiddle is buggy, at least, I cannot get any response from it when I change the IO settings. On a real site, having a fixed top margin and variable bottom margin is viewport-height dependent: the top margin must be higher up in the viewport than the bottom margin, otherwise the CB doesn't fire. I think this is part of the issue in JSFiddle - the viewport is very short. For instance, with rootMargin:'-50px 0px -90% 0px' the viewport (window.innerHeight) must be at least 500px (actually ~490px worked) so that the div you are observing triggers the viewport's bottom margin at least 50px (10% of innerHeight) down from the top BEFORE it hits the top margin a fixed 50px from the top. If the bottom is inside (that is, above) the top it won't fire. For any viewport, though again I couldn't get anything from JSFiddle, this seemed to work: rootMargin:'0px 0px -100% 0px'. This will not trigger the IO callback until the grey div's top reaches the top of the viewport, and as you keep scrolling the grey div will be intersecting until it is off-screen. The hamburger menu class changes accordingly.

James South
  • 534
  • 4
  • 15