Detecting Scroll & Resize Events with onscroll and onresize

This guide covers how to use the `onscroll` and `onresize` events in JavaScript to detect scroll and resize actions, including detailed examples and practical applications.

Introduction to Scroll and Resize Events

When building web applications, understanding how users interact with the content is crucial. Two common types of interactions are scrolling and resizing. Scroll and resize events allow developers to execute specific actions when these interactions occur, enhancing user experience and functionality.

Understanding the Purpose

Scroll and resize events are fundamental in creating dynamic web applications. These events help in triggering specific functions when the user scrolls down a webpage or resizes the browser window. This can be used for a variety of purposes such as loading more content on scroll (infinite scrolling), adjusting the layout when the window size changes (responsive design), and much more.

Importance in Web Development

In web development, these events are essential for creating interactive and responsive websites. They allow developers to make webpages more engaging by responding to user actions in real-time. For instance, sticky headers, lazy loading images, and dynamic content adjustments are all possible through these events.

The onscroll Event

The onscroll event in JavaScript is triggered every time the user scrolls through a web page. This event can be attached to the window object or any other scrollable element such as a <div>.

Basic Syntax and Usage

The basic syntax for using the onscroll event is straightforward:

window.onscroll = function() {
  console.log("Page is scrolling");
};

This code snippet attaches a function to the onscroll event of the window object. Whenever the user scrolls, the message "Page is scrolling" is logged to the console.

Example: Logging Scroll Position

Let's create an example where we log the current scroll position each time the user scrolls:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll Position Logger</title>
    <style>
        body {
            height: 2000px; /* Make the page scrollable */
            margin: 0;
        }
        #log {
            position: fixed;
            top: 10px;
            left: 10px;
            background: white;
            padding: 10px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <div id="log">Scroll Position: 0</div>
    <script>
        window.onscroll = function() {
            var scrollPosition = window.scrollY;
            document.getElementById("log").innerText = "Scroll Position: " + scrollPosition;
        };
    </script>
</body>
</html>

Explanation: How onscroll Works

In the example above, we added a div with the id log to display the scroll position. The JavaScript function attached to window.onscroll calculates the vertical scroll position using window.scrollY and updates the inner text of the div accordingly. This provides a real-time log of the user's scroll position.

Practical Applications

Example: Sticky Headers

A sticky header is a navigation bar that remains at the top of the page even when the user scrolls. Here’s how you can create a sticky header using the onscroll event:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sticky Header Example</title>
    <style>
        body {
            height: 2000px; /* Add extra height to make the page scrollable */
            margin: 0;
        }
        header {
            position: fixed;
            top: 0;
            width: 100%;
            background-color: #333;
            color: white;
            padding: 10px;
            transition: top 0.3s;
        }
    </style>
</head>
<body>
    <header id="header">
        Sticky Header
    </header>
    <script>
        window.onscroll = function() {
            var header = document.getElementById("header");
            if (window.scrollY > 100) {
                header.style.top = "0"; // Stick the header to the top of the screen
            } else {
                header.style.top = "-50px"; // Hide the header when at the top of the page
            }
        };
    </script>
</body>
</html>

In this example, the onscroll event checks if the vertical scroll position (window.scrollY) is greater than 100 pixels. If it is, the header's top position is set to 0 making it stick to the top. Otherwise, it is hidden by setting its top position to -50px.

Example: Infinite Scrolling

Infinite scrolling is a technique where more content is loaded automatically as the user scrolls down. Here’s a simple example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Infinite Scrolling Example</title>
    <style>
        body {
            margin: 0;
            padding: 20px;
        }
        .content {
            height: 300px;
            margin-bottom: 50px;
            padding: 20px;
            border: 1px solid #ccc;
            background-color: #f9f9f9;
        }
    </style>
</head>
<body>
    <div id="content">
        <div class="content">Content 1</div>
        <div class="content">Content 2</div>
        <div class="content">Content 3</div>
    </div>
    <script>
        const contentDiv = document.getElementById("content");

        window.onscroll = function() {
            if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
                setTimeout(() => {
                    const newContent = document.createElement("div");
                    newContent.className = "content";
                    newContent.innerText = "New Content";
                    contentDiv.appendChild(newContent);
                }, 500); // Simulate network request delay
            }
        };
    </script>
</body>
</html>

In this example, the onscroll event checks if the sum of the viewport height (window.innerHeight) and the vertical scroll position (window.scrollY) is greater than or equal to the total height of the document (document.body.offsetHeight). If true, it simulates loading new content by creating a new div element and appending it to the existing content after a 500 ms delay to mimic a network request.

The onresize Event

The onresize event is triggered whenever the size of a window (or any other resizable element) is changed. This event is particularly useful for creating responsive designs that adjust to different screen sizes.

Basic Syntax and Usage

The basic syntax for using the onresize event is:

window.onresize = function() {
  console.log("Window is resizing");
};

This code snippet executes the function inside onresize every time the browser window is resized, logging the message "Window is resizing" to the console.

Example: Logging Window Size

Let's create an example that logs the current window size each time it is resized:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Resize Logger</title>
    <style>
        #log {
            position: fixed;
            top: 10px;
            right: 10px;
            background: white;
            padding: 10px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <div id="log">Window Size: </div>
    <script>
        window.onresize = function() {
            var width = window.innerWidth;
            var height = window.innerHeight;
            document.getElementById("log").innerText = "Window Size: " + width + "x" + height;
        };
    </script>
</body>
</html>

Explanation: How onresize Works

In this example, the onresize event calculates the window's width (window.innerWidth) and height (window.innerHeight) and updates the inner text of the div with the id log with the new dimensions. This logs the window size in real-time as the user resizes the browser.

Practical Applications

Example: Responsive Layouts

Responsive layouts automatically adjust their design based on the window size. Here’s an example using the onresize event:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Layout</title>
    <style>
        body {
            margin: 0;
            font-family: Arial, sans-serif;
        }
        .container {
            padding: 20px;
            border: 1px solid #ccc;
        }
        .responsive {
            width: 100%;
            height: 200px;
            background-color: #eee;
            text-align: center;
            line-height: 200px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="responsive" id="responsive">
            Resize me!
        </div>
    </div>
    <script>
        window.onresize = function() {
            const responsiveDiv = document.getElementById("responsive");
            if (window.innerWidth < 600) {
                responsiveDiv.style.backgroundColor = "lightblue";
            } else {
                responsiveDiv.style.backgroundColor = "lightgreen";
            }
        };
    </script>
</body>
</html>

In this example, the onresize event checks the window width. If it’s less than 600 pixels, the background color of the div changes to light blue. Otherwise, it changes to light green. This demonstrates a basic responsive design that reacts to window size changes.

Example: Dynamic Content Adjustments

Dynamic content adjustments can be used to improve the user experience by modifying the content based on the screen size. Here’s how you can dynamically adjust content using the onresize event:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Content Adjustments</title>
    <style>
        body {
            margin: 0;
        }
        .content {
            padding: 20px;
            border: 1px solid #ccc;
        }
        .content-inner {
            text-align: center;
            font-size: 20px;
        }
    </style>
</head>
<body>
    <div class="content">
        <div class="content-inner" id="content-text">
            Adjusting content based on window size.
        </div>
    </div>
    <script>
        window.onresize = function() {
            const contentText = document.getElementById("content-text");
            if (window.innerWidth < 600) {
                contentText.innerText = "This is a smaller screen.";
                contentText.style.fontSize = "16px";
            } else {
                contentText.innerText = "This is a larger screen.";
                contentText.style.fontSize = "20px";
            }
        };
    </script>
</body>
</html>

In this example, when the window width is less than 600 pixels, the content text changes to "This is a smaller screen" and the font size is reduced to 16px. For larger screens, the content text changes to "This is a larger screen" with a font size of 20px.

Comparing onscroll and onresize

Similarities and Differences

Both onscroll and onresize events are used to handle changes in the browser window, but they serve different purposes. The onscroll event is used specifically for detecting scrolling actions, while the onresize event is used for detecting window resizing. However, both can be attached to any scrollable or resizable element.

Choosing Between onscroll and onresize

Choosing between onscroll and onresize depends on the specific requirement. If you need to perform actions based on user scrolling, use onscroll. If you need to handle changes in window size for responsive design, use onresize.

Performance Considerations

Frequent triggering of onscroll and onresize events can lead to performance issues if not handled properly. The functions attached to these events can be called very frequently, especially on smaller devices with faster scrolling and resizing actions. To handle this, techniques like throttling and debouncing are commonly used.

Throttling and Debouncing

Throttling limits the rate at which a function can be executed. Debouncing only allows a function to be executed after a period of inactivity. Both techniques are effective in managing the frequency of function calls.

Here’s an example of both techniques:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Throttle vs Debounce</title>
    <style>
        body {
            margin: 0;
            height: 2000px; /* Make page scrollable */
        }
        #log {
            position: fixed;
            top: 10px;
            left: 10px;
            background: white;
            padding: 10px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <div id="log">Scroll or Resize</div>
    <script>
        function logEvent(message) {
            const log = document.getElementById("log");
            log.innerText = message;
        }

        function throttle(func, limit) {
            let lastFunc;
            let lastRan;
            return function() {
                const context = this;
                const args = arguments;
                if (!lastRan) {
                    func.apply(context, args);
                    lastRan = Date.now();
                } else {
                    clearTimeout(lastFunc);
                    lastFunc = setTimeout(function() {
                        if ((Date.now() - lastRan) >= limit) {
                            func.apply(context, args);
                            lastRan = Date.now();
                        }
                    }, limit - (Date.now() - lastRan));
                }
            };
        }

        function debounce(func, limit) {
            let inDebounce;
            return function() {
                const context = this;
                const args = arguments;
                clearTimeout(inDebounce);
                inDebounce = setTimeout(() => func.apply(context, args), limit);
            };
        }

        const scrollLogger = throttle(function() {
            logEvent("Throttled Scroll");
        }, 300);

        const resizeLogger = debounce(function() {
            logEvent("Debounced Resize");
        }, 300);

        window.onscroll = scrollLogger;
        window.onresize = resizeLogger;
    </script>
</body>
</html>

In this example, we created two helper functions, throttle and debounce, to limit how frequently the event handlers can execute. The scrollLogger function is throttled to run only every 300 milliseconds, while the resizeLogger function is debounced to run only once 300 milliseconds after the resizing stops.

Advanced Techniques for Handling Scroll and Resize Events

Using Event Listeners for Better Control

Using event listeners provides more control over handling the events. Event listeners can be attached and removed dynamically, and they can be used to handle multiple events on the same element.

Syntax and Usage

To add an event listener, use the addEventListener method:

window.addEventListener("scroll", function() {
    console.log("Page is scrolling");
});

To remove an event listener, use the removeEventListener method:

function handleScroll() {
    console.log("Page is scrolling");
}

window.addEventListener("scroll", handleScroll);

// To remove the event listener
window.removeEventListener("scroll", handleScroll);

Example: Adding and Removing Event Listeners

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Event Listeners Example</title>
    <style>
        body {
            height: 2000px; /* Make page scrollable */
        }
        #log {
            position: fixed;
            top: 10px;
            right: 10px;
            background: white;
            padding: 10px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <div id="log">Scroll or Resize</div>
    <button id="addEvent">Add Event Listener</button>
    <button id="removeEvent">Remove Event Listener</button>
    <script>
        const log = document.getElementById("log");
        const addEventButton = document.getElementById("addEvent");
        const removeEventButton = document.getElementById("removeEvent");

        function handleScroll() {
            log.innerText = "Scroll Event Triggered";
        }

        addEventButton.addEventListener("click", function() {
            window.addEventListener("scroll", handleScroll);
            log.innerText = "Scroll Event Listener Added";
        });

        removeEventButton.addEventListener("click", function() {
            window.removeEventListener("scroll", handleScroll);
            log.innerText = "Scroll Event Listener Removed";
        });
    </script>
</body>
</html>

In this example, we have two buttons to add and remove the scroll event listener. Clicking on "Add Event Listener" adds the handleScroll function to the scroll event, and clicking on "Remove Event Listener" removes it.

Delegating Events

Event delegation is a technique where a single event listener is added to a parent element to handle events that occur on its child elements. This approach is more efficient, especially when dealing with a large number of similar elements.

Explanation: What is Event Delegation

Event delegation leverages the concept of event propagation in JavaScript. Instead of adding an event listener to every child element, you add a single event listener to the parent element and determine which child element triggered the event through the event object.

Example: Delegating Scroll and Resize Events

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Event Delegation</title>
    <style>
        body {
            height: 2000px; /* Make page scrollable */
        }
        #log {
            position: fixed;
            top: 10px;
            left: 10px;
            background: white;
            padding: 10px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <div id="log">Scroll or Resize</div>
    <script>
        window.addEventListener("scroll", function(event) {
            document.getElementById("log").innerText = "Scroll Event Detected";
        });

        window.addEventListener("resize", function(event) {
            document.getElementById("log").innerText = "Resize Event Detected";
        });
    </script>
</body>
</html>

In this example, we removed the need to add separate functions for onscroll and onresize by using event listeners. Both events log a message to the log div when triggered.

Capturing vs. Bubbling Phases

JavaScript events propagate through three phases:

  1. Capturing Phase: Event starts from the window down to the target element.
  2. Target Phase: Event reaches the target element.
  3. Bubbling Phase: Event bubbles up from the target element to the window.

Understanding these phases helps in controlling when and how events are handled.

Explanation: Event Propagation in JavaScript

Event propagation is important when dealing with nested elements. By default, event listeners are set to the bubbling phase. You can change this behavior by setting the third parameter of addEventListener to true for the capturing phase.

Practical Implications for Scroll and Resize Events

For scroll and resize events, event propagation is generally not an issue since these events do not bubble. However, understanding this concept is useful when combining multiple event listeners on parent and child elements.

Conclusion on Scroll and Resize Events

Summarizing Key Points

  • onscroll triggers when the user scrolls through the page.
  • onresize triggers when the browser window is resized.
  • Throttling and debouncing can be used to manage performance for frequently triggering events.
  • Event listeners provide more control over handling events compared to the direct event handlers.

Best Practices for Implementation

  • Use event listeners for better control and flexibility.
  • Consider performance by throttling and debouncing event handlers.
  • Always remove event listeners when they are no longer needed to prevent memory leaks.

Further Reading and Resources

Exercise and Practice

Hands-On Practice

Tasks: Implementing Scroll and Resize Events

  1. Create a webpage that changes the background color of the body based on the scroll position.
  2. Create a responsive image gallery that adjusts the image size based on window resize.

Tasks: Applying Best Practices in Project Contexts

  1. Implement throttling or debouncing on a scroll event that updates a log of scroll positions.
  2. Use event listeners to manage scroll and resize events instead of direct event handlers.

Solutions and Feedback

Discussion: Student Questions and Answers

Feel free to ask questions about the examples, best practices, and any other aspects of scroll and resize events. Here are some potential questions and answers:

  • Q: Can onscroll and onresize be used together on the same page?

    • A: Yes, absolutely! You can attach separate handlers for each event on the same element or the same type of element.
  • Q: What are the advantages of using event listeners over direct event handlers?

    • A: Event listeners provide more control and flexibility, allowing you to add or remove them dynamically. They also support multiple handlers for the same event type, which is not possible with direct event handlers.

By understanding and effectively using onscroll and onresize events, you can create more interactive and responsive web applications. Practice the examples and exercises provided to gain hands-on experience and deepen your understanding of these essential JavaScript events.


This comprehensive guide should give you a solid foundation for using scroll and resize events in JavaScript, offering practical examples and best practices to help you in your web development journey.