Home > Net >  Add class to one div when another is in the viewport
Add class to one div when another is in the viewport

Time:03-27

I have a website using vertical scroll snap. The website is divided into full width and height sections and I would like to style the navigation and other elements depending on which of these sections in in the viewport.

I have tried a lot of answers I have found online without success. The closest I can get it to work is this:

var targets = document.querySelectorAll('section')
var obsOptions = {
  root: null, // measure against the viewport
  threshold: .5 // how much of the element should be visible before handler is triggered
}

let handler = (entries, opts) => {
  entries.forEach(entry => {
    if (entry.intersectionRatio > opts.thresholds[0]) {
      document.body.classList.remove(...document.body.classList);
      document.body.classList.add(entry.target.id   '-active');
    }
  })
}

targets.forEach(el => {
  var observer = new IntersectionObserver(handler, obsOptions);
  observer.observe(el);
})

This works well except it removes all the classes off the body and the WordPress theme adds its own which are necessary for it to function so I can't have that

If I remove the line about removing the classes - ALL the section ID's show as classes at the same time.

I thought the best way would be to not apply it to the body, but to a container that had no other classes - so I have wrapped everything in a container div with a class of

.full-page-container

I tried editing the code to this

var targets = document.querySelectorAll('section')
var obsOptions = {
  root: null, // measure against the viewport
  threshold: .5 // how much of the element should be visible before handler is triggered
}

let handler = (entries, opts) => {
  entries.forEach(entry => {
    if (entry.intersectionRatio > opts.thresholds[0]) {
      document.full-page-container.classList.remove(...document.ful-page-container.classList);
      document.full-page-container.classList.add(entry.target.id   '-active');
    }
  })
}

targets.forEach(el => {
  var observer = new IntersectionObserver(handler, obsOptions);
  observer.observe(el);
})

but it doesn't work.

How does one apply this same effect to a div rather than the body

Any help would be much appreciated

Here is a codepen I have put together

https://codepen.io/shereewalker/pen/bGaqqmy

CodePudding user response:

In the remove you are spending the content of classList and I think therefore are removing all the classes.

I would suggest filtering the classList for classes that contain -active (The class you add) and then removing those.

var targets = document.querySelectorAll('section')
var obsOptions = {
  root: null, // measure against the viewport
  threshold: .5 // how much of the element should be visible before handler is triggered
}

let handler = (entries, opts) => {
  entries.forEach((entry) => {
    if (entry.intersectionRatio > opts.thresholds[0]) {
      const classesToRemove = findClassesWithActive(document.body.classList);
      if (classesToRemove.length > 0) {
        document.body.classList.remove(classesToRemove);
      }
      document.body.classList.add(entry.target.id   "-active");
    }
  });
};

targets.forEach(el => {
  var observer = new IntersectionObserver(handler, obsOptions);
  observer.observe(el);
})
    function findClassesWithActive(classList) {
       return classList.filter(c => c.includes('-active')
    }

Codepenne with it working

  • Related