Javascript window scroll movement capture upscroll without JQuery

Hi there everyone,

$(window).scroll(function(){
	if($(window).scrollTop() >1) {
		$(".topheader").addClass("active");	
	}
	else {
		$(".topheader").removeClass("active");
	}
});

The above is a JQuery code whose some part I can easily handle, but how to convert them to javascript:

$(window).scroll(function(){
if($(window).scrollTop() >1) {

I came up with this version, but I belive this has syntax issues:

window.addEventListener('scroll', function() {
	if(window.scrollTop > 1) {
		var topHeader  = document.getElementsByTagName('.topheader');
		topHeader.classList.add("active");		
	}else{
		topHeader.classList.remove("active");
	}
});

It might be because you are using a CSS term in an element selector. Using querySelector is the preferred way to do that these days.

Also, the classList API supports toggle, which can help out here.

window.addEventListener('scroll', function() {
	var topHeader  = document.querySelector('.topheader');
	topHeader.classList.toggle("active", window.scrollTop > 1);
});
1 Like

Thank you so much, Sir if we want to put two conditions if we are up scrolling and the scroll is at least 100px from the top?

There are certain function available in javascript → https://www.w3schools.com/jsref/met_win_scrollby.asp

I was unable to determine how to make use of them, I want that active class should be injected when:

  1. We are scrolling upwards.
  2. We are at least some pixes away from the top.

Then we use local variables for those things.

window.addEventListener('scroll', function() {
	var topHeader  = document.querySelector('.topheader');
        var isScrolled = window.scrollTop > 1;
        var otherCondition = true;
        var shouldToggle = isScrolled && otherCondition;
	topHeader.classList.toggle("active", shouldToggle);
});

When it comes to upscrolling, that can only be determined by comparing with a previous scroll amount.
The other situation of being within 100px is much easier to check.

I’ll leave you to work on this yourself for a bit, as that’s where the most learning occurs.

2 Likes

How should we register the previous scroll? Because the scroll(when the user is interacting with the scrolling event) is a continuous and often random(scrolling up and down) process. Current can be done, but previous?

I didnt tried on my live project, but I think I am able to get to it:

var lastScroll = 0;
window.addEventListener('scroll', function() {	
	var topHeader  = document.querySelector('.topheader');
	var isScrolled = window.scrollTop > 1;
	var currentScroll = window.pageYOffset;
	var scrollDirection = (currentScroll - lastScroll) < 0;
	console.log(scrollDirection);
	var shouldToggle = isScrolled && scrollDirection;
	topHeader.classList.toggle("active", shouldToggle);
	var lastScroll = currentScroll;
});

var lastScroll = 0;

If I put var lastScroll = 0; outside window addeventlistener I get NAN, and if I put it just inside addvenetlistener, irrespective of what is assigned in the bottom when we had set →

var lastScroll = currentScroll;

It gets reassinged to var lastScroll = 0;

You can’t declare the same variable twice ( lastScroll )? (Well you can but it won’t work)

You just want: lastScroll = currentScroll; inside that function.

What’s the difference between window.pageYOffset and window.scrollTop. I believe you need something like:

  var currentScroll =
    window.pageYOffset ||
    document.documentElement.scrollTop ||
    document.body.scrollTop ||
    0;

I’m sure @Paul_Wilkins will have something to say about that. :slight_smile:

I think you are trying something like this (but as you know I’m not much more advanced than you at js)

I merely show it for learning purposes (for both of us) and not as an example to copy :wink:

1 Like

I got my mistake that variable or var can be assigned new value, but it can use same keyword twice - The fix:

Yes that’s what I was saying. You used ‘var’ again when you only needed to update the variable itself with a new value.:slight_smile:

You still need to sort scrollTop as it is undefined in Firefox and Chrome.

I think your code should be this:

var lastScroll = 0;
window.addEventListener("scroll", function () {
  var topHeader = document.querySelector(".topheader");
  var currentScroll = window.pageYOffset;
  var isScrolled = currentScroll > 1;
  var scrollDirection = currentScroll - lastScroll < 0;
  var shouldToggle = isScrolled && scrollDirection;
  topHeader.classList.toggle("active", shouldToggle);
  lastScroll = currentScroll;
});

But I’m guessing that you need the version I posted before for wider browser support.

 var currentScroll =
    window.pageYOffset ||
    document.documentElement.scrollTop ||
    document.body.scrollTop ||
    0;
1 Like

Hi there, I think you made a typological error.

var scrollDirection = currentScroll > lastScroll; should be:

var scrollDirection = currentScroll < lastScroll;

to ensure that the menu appears when we scroll upward.

1 Like

Yes I’ve already changed it :slight_smile: (Sorry)

1 Like

Could this help:

var isScrolled = window.pageYOffset > 1;

Ammendment: I tried this and it is working.

Yes you need to research the difference between that and scrollTop and why you might need the version I posted above.

You may be interested in this old version that @Paul_Wilkins tidied up for me in an old thread. It uses jquery but is the same idea. It also has a debounce function added so that the scroll event isn’t slowing down the page.

The scroll event fires continuously when scrolling so you really need to debounce it or it slows heavy pages down.

1 Like

I was doing something else with Javascript and came to know about this property: getBoundingClientRect()Mozilla Link Here

I used this property to get the anticipated result, and come up with this working version:

var lastScroll = 0;
window.addEventListener('scroll', function() {
	var stickyHeader  = document.querySelector(".header");		
	var isScrolled = window.pageYOffset > 1;
	currentScroll = document.body.getBoundingClientRect().top;
	var scrollDirection = currentScroll > lastScroll;
	var shouldToggle = isScrolled && scrollDirection;
	stickyHeader.classList.toggle("active", shouldToggle);
	lastScroll = currentScroll;
});

It has not minimized the lines of code but utilizes another property to achieve the desired result.

Top is treated as 0 point so this will give negative value: document.body.getBoundingClientRect().top so we have to adjust equality/inequality in scrollDirection reciprocal to what we did in previous version.

1 Like

In web pages we have one click page scrolls, I have designed that but I wanted to achieve that scroll should be smooth. I am using vanilla JS code. I know how to do that in JS, but in JS?

var lastScroll = 0;
window.addEventListener('scroll', function() {
	var stickyHeader  = document.querySelector(".header");		
	var isScrolled = window.pageYOffset > 1;
	var currentScroll = document.body.getBoundingClientRect().top;
	var scrollDirection = currentScroll > lastScroll;
	var shouldToggle = isScrolled && scrollDirection;
	stickyHeader.classList.toggle("active", shouldToggle);	
	lastScroll = currentScroll;
	var idArrowScrollUp  = document.querySelector("#arrowScrollUp");
	var arrowScrollUp = window.pageYOffset >= 50;
	idArrowScrollUp.classList.toggle("arrowScrollUp", arrowScrollUp);
});

This part is handling that one click whole page scroll to top →

var idArrowScrollUp  = document.querySelector("#arrowScrollUp");
var arrowScrollUp    = window.pageYOffset >= 50;
idArrowScrollUp.classList.toggle("arrowScrollUp", arrowScrollUp);

I assume you meant you know how to do it in Jquery not JS :slight_smile:

Or did you mean CSS as you can smooth scroll to destinations without any JS these days?

1 Like

That’s right sorry for the typo mistake. I have uploaded the code online. In the bottom right you will find an arrow, which on click will send the whole page up that scroll is unsmooth. There must be some time function and may be css can fit here.

Just use this:

html,
body {
  scroll-behavior: smooth;
}
1 Like