Why did I call the scroll event before registering the event listener and the event listener is fired?

Viewed 264

   window.scroll(0,10);
   window.addEventListener('scroll', function(e){
     console.log("event!");  
   });

  1. I registered an event listener after the scroll event, but why is "event!" being displayed on the console?
  2. Why did "event!" appear on the console twice when the scroll happened once?
3 Answers

"scroll" event is very sensitive event. It is so much sensitive that using event.preventDefault() is not useful in its event listener as scroll happens before event.preventDefault() can execute. I have created a code using your code snippet as:

<!DOCTYPE html>
<html>

<head>
    <style>
        .large-div {
            height: 200vh;
            width: 98vw;
            background-color: #ccc;
            text-align: center;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow-x: hidden;
        }
    </style>
</head>

<body>
    <div class="large-div">
        <h3>Scroll Me</h3>
    </div>
    <script>
        window.scroll(0, 10);
        window.addEventListener('scroll', function (e) {
            const lastScrollPosition = window.scrollY;
            console.log(lastScrollPosition);
        });
    </script>
</body>

</html>

I found that when we open page first time in browser, scroll event is triggered once but, when I refresh the page, scroll event get triggered twice. What I get from this behavior is that if there is default scroll on the page, then scroll event will be triggered as page loads and it is due to some minor movement in the scroll.

I have created one more animated demonstration to understand this. Here, I am using the animation to increase the height. Initial height is 10vh which implies page will load without any scroll. On clicking 'Resize' button, animation will start, box color will turn to black and as animation ends, box color will turn back to grey. Here I notice, that even though scroll start coming on the window, but event for scroll not get triggered until I manually scroll the window.

<!DOCTYPE html>
<html>

<head>
    <style>
        .large-div {
            height: 10vh;
            width: 98vw;
            background-color: #ccc;
            text-align: center;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow-x: hidden;
        }

        .apply-resize-animation {
            animation-name: resize-animation;
            animation-duration: 4s;
            animation-fill-mode: forwards;
        }

        @keyframes resize-animation {
            0% {
                height: 10vh;
                background-color: #000;
            }

            25% {
                height: 70vh;
                background-color: #000;
            }

            50% {
                height: 120vh;
                background-color: #000; 
            }

            100% {
                height: 200vh;
                background-color: #ccc;
            }
        }
    </style>
</head>

<body>
    <div class="large-div">
        <button id="resize-btn">Resize Me</button>
    </div>
    <script>
        window.scroll(0, 10);
        window.addEventListener('scroll', function (e) {
            const lastScrollPosition = window.scrollY;
            console.log('Last scroll position');
            console.log(lastScrollPosition);
        });
        document.getElementById('resize-btn').addEventListener('click', function (e) {
            console.log('Resize btn clicked!');
            const toResizeElement = document.querySelector("div.large-div");
            if (!toResizeElement.classList.contains("apply-resize-animation")) {
                toResizeElement.classList.add("apply-resize-animation");
            }
        });
    </script>
</body>

</html>

The reason your scroll handler is called twice might be because the browser attempts to restore scroll position as it was before you refreshed the page.

To verify this

  1. Remove window.scroll(0,10);
  2. Scroll page manually downwards
  3. Refresh the page
  4. Notice that your event gets triggered.

As for why the 'scroll' event is being triggered even if window.scroll is called before registering the handler, this seems to be related to:

This answer might have some more pointers https://stackoverflow.com/a/59559610/149636

Guess:

  1. I registered an event listener after the scroll event, but why is "event!" being displayed on the console?
window.scroll(0,10) // Async execute and scroll called trigger onscroll event
window.addEventListener('scroll', ...) // Registered scroll sync execute
  1. Why did "event!" appear on the console twice when the scroll happened once?

Scroll is 2D, because has x,y coordinate point.

Related