简体   繁体   中英

How do I update an element class based on a separate element's active class?

I am trying to reproduce the effect on Chaptr's website, about half way down the page, where scrolling past a list elements changes the class of separate elements that are sticky/fixed. Example here: https://chaptr.studio/ , "Brand, Creative, Code, Growth," section.

I've managed to get part of the effect to work with the following code, although it isn't the cleanest. Is there anyway I could get the left hand list of elements "Investments, Education, Mentoring" to match what is happening with the non-sticky list.

const halfWindow = (window.innerHeight / 2) - 50
const listItems = document.querySelectorAll('.scroll-item')

const firstItem = listItems[0]
const lastItem = listItems[listItems.length - 1]

const updateSection = () => {
  const pixels = window.pageYOffset

  listItems.forEach(item => {

    // find the position of each item
    const itemTop = item.offsetTop - pixels
    const itemBottom = (item.offsetTop + item.offsetHeight) - pixels

    // first item top
    const firstItemTop = firstItem.offsetTop - pixels
    const firstItemBottom = (firstItem.offsetTop + firstItem.offsetHeight) - pixels

    // target the first item in the array
    if (firstItemBottom <= halfWindow) {
      firstItem.classList.remove('active')
      firstItem.classList.remove('current')
    } else if (firstItemBottom >= halfWindow) {
      firstItem.classList.add('current')
    }

    // working sort of - clean up
    if ((itemTop <= halfWindow) && (itemBottom <= halfWindow)) {
      item.classList.remove('active')   
      if (item === lastItem) {
        item.classList.add('current')
      }
    } else if ((itemTop <= halfWindow) && (itemBottom >= halfWindow)) {
      item.classList.add('active')
      item.classList.remove('current')
    } else {
      item.classList.remove('active')
    }

  })
}

document.addEventListener("scroll", updateSection)

Here is a codepen example: https://codepen.io/anon/pen/gVOZzp ?

The main bit I need to figure out is how to match the left hand list items to active, when each list item on the right becomes "active".

One way to do it is like this. First, select all inner items to work with storing them in a global variable :

const innerItems = document.querySelectorAll('.sticky-inner li');

Then, you can add this in the end of updateSection function :

  if (document.querySelector('.sticky-inner .active')) {
    document.querySelector('.sticky-inner .active').classList.remove('active');
  }
  if (listItems[0].classList.contains('active')) {
    innerItems[0].classList.add('active');
  } else if (listItems[1].classList.contains('active')) {
    innerItems[1].classList.add('active');
  } else if (listItems[2].classList.contains('active')) {
    innerItems[2].classList.add('active');
  }

It will always compare both hands to match them and add/remove the active class .

In the end I set up the variable like Azametzin said with:

const innerItems = document.querySelectorAll('.sticky-inner li')

Then using classList.contains and getAttribute , compared both lists – checking to see if they matched. See code below:

const updateSectionHeadings = () => {

  listItems.forEach(item => {

    // if the item has the active or current class
    if (item.classList.contains('active') || item.classList.contains('current')) {

      // set itemData to the data attribute's value
      let itemData = item.getAttribute('data-name')

      // loop through the section list
      innerItems.forEach(innerItem => {
        // set innerItemData to the data attribute's value
        let innerItemData = innerItem.getAttribute('data-name')

        if (itemData !== innerItemData) {
          // if itemData is not the same as innerItemData
          innerItem.classList.remove('active')
        } else if (itemData === innerItemData) {
          // if itemData is the same as innerItemData
          innerItem.classList.add('active')
        }

      })

    }

  })

}

document.addEventListener("scroll", updateSectionHeadings)
window.addEventListener("resize", updateSectionHeadings)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM