Hejha
Hejha

Reputation: 29

Fast scroll to change style

Is it possible to scroll to .project and make the background red without to scroll slow and near the class .project?

Basically I want the user to be able to scroll and get the red color displayed even if he or she scrolls quickly, but when the user is above or under projectPosition.top, the background should be the standard color (black).

var project = document.getElementsByClassName('project')[0];
var projectPosition = project.getBoundingClientRect();

document.addEventListener('scroll', () => {

    var scrollY = window.scrollY;
    
    if (scrollY == projectPosition.top) {
        project.style.background = "red";
        project.style.height = "100vh";
    } else {
        project.style.background = "black";
        project.style.height = "200px";
    }
    
});
.top {
  height: 700px;
}

.project {
  background: black;
  height: 200px;
  width: 100%;
}
<div class="top"></div>
<div class="project"></div>
<div class="top"></div>

Thanks in advance.

Upvotes: 0

Views: 59

Answers (2)

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20944

Instead of listen for the scroll event you could use the Intersection Observer API which can monitor elements that come in and out of view. Every time an observed element either enters or leaves the view, a callback function is fired in which you can check if an element has entered or left the view, and handle accordingly.

It's also highly performant and saves you from some top and height calculations. Check it out in the example below.

If you have any questions about it, please let me know.

Threshold

To trigger the callback whenever an element is fully into view, not partially, set the threshold option value to [1]. The default is [0], meaning that it is triggered whenever the element is in view by a minimum of 1px. [1] states that 100% of the element has to be in view to trigger. The value can range from 0 to 1 and can contain multiple trigger points. For example

const options = {
  threshold: [0, 0.5, 1]
};

Which means, the start, halfway, and fully in to view.

const project = document.querySelector('.project');

const observerCallback = entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('red');
    } else {
      entry.target.classList.remove('red');
    }
  });
};

const options = {
  threshold: [1]
}

const observer = new IntersectionObserver(observerCallback, options);
observer.observe(project);
.top,
.bottom{
  height: 700px;
  width: 100%;
}

.project {
  background: black;
  height: 200px;
  width: 100%;
}

.project.red {
  background: red;
}
<div class="top"></div>
<div class="project"></div>
<div class="bottom"></div>

Upvotes: 3

johannchopin
johannchopin

Reputation: 14853

To make it 'fast' you better will have to use the >= operator than ==:

var project = document.getElementsByClassName('project')[0];
var projectPosition = project.getBoundingClientRect();

document.addEventListener('scroll', () => {

    var scrollY = window.scrollY;
    if (scrollY >= projectPosition.top && scrollY <= projectPosition.top + projectPosition.height) {
        project.style.background = "red";
        project.style.height = "100vh";
    } else {
        project.style.background = "black";
        project.style.height = "200px";
    }
    
});
.top {
  height: 700px;
}

.project {
  background: black;
  height: 200px;
  width: 100%;
}
<div class="top"></div>
<div class="project"></div>
<div class="top"></div>

Upvotes: 0

Related Questions