Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Error’d: You Talkin’ to Me?

      September 20, 2025

      The Psychology Of Trust In AI: A Guide To Measuring And Designing For User Confidence

      September 20, 2025

      This week in AI updates: OpenAI Codex updates, Claude integration in Xcode 26, and more (September 19, 2025)

      September 20, 2025

      Report: The major factors driving employee disengagement in 2025

      September 20, 2025

      Development Release: Zorin OS 18 Beta

      September 19, 2025

      Distribution Release: IPFire 2.29 Core 197

      September 19, 2025

      Development Release: Ubuntu 25.10 Beta

      September 18, 2025

      Development Release: Linux Mint 7 Beta “LMDE”

      September 18, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      The attack on the npm ecosystem continues

      September 20, 2025
      Recent

      The attack on the npm ecosystem continues

      September 20, 2025

      Feature Highlight

      September 20, 2025

      SVAR React Core – New UI Library with 20+ Components

      September 20, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Hyprland Made Easy: Preconfigured Beautiful Distros

      September 20, 2025
      Recent

      Hyprland Made Easy: Preconfigured Beautiful Distros

      September 20, 2025

      Development Release: Zorin OS 18 Beta

      September 19, 2025

      Distribution Release: IPFire 2.29 Core 197

      September 19, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»News & Updates»A Better API for the Resize Observer

    A Better API for the Resize Observer

    June 16, 2025

    Resize Observer, Mutation Observer, and Intersection Observers are all good APIs that are more performant than their older counterparts:

    • ResizeObserver is better than the resize event
    • MutationObserver replaces the now deprecated Mutation Events
    • IntersectionObserver lets you do certain scroll interactions with less performance overhead.

    The API for these three observers are quite similar (but they have their differences which we will go into later). To use an observer, you have to follow the steps below:

    1. Create a new observer with the new keyword: This observer takes in an observer function to execute.
    2. Do something with the observed changes: This is done via the observer function that is passed into the observer.
    3. Observe a specific element: By using the observe method.
    4. (Optionally) unobserve the element: By using the unobserve or disconnect method. (depending on which observer you’re using).

    In practice, the above steps looks like this with the ResizeObserver.

    // Step 1: Create a new observer
    const observer = new ResizeObserver(observerFn)
    
    // Step 2: Do something with the observed changes
    function observerFn (entries) {
      for (let entry of entries) {
        // Do something with entry
      }
    }
    
    // Step 3: Observe an element
    const element = document.querySelector('#some-element')
    observer.observe(element);
    
    // Step 4 (optional): Disconnect the observer
    observer.disconnect(element)

    This looks clear (and understandable) after the steps have been made clear. But it can look like a mess without the comments:

    const observer = new ResizeObserver(observerFn)
    
    function observerFn (entries) {
      for (let entry of entries) {
        // Do something with entry
      }
    }
    
    const element = document.querySelector('#some-element')
    observer.observe(element);

    The good news is: I think we can improve the observer APIs and make them easier to use.

    The Resize Observer

    Let’s start with the <a href="https://splendidlabz.com/docs/utils/dom/resize-observer" rel="noopener">ResizeObserver</a> since it’s the simplest of them all. We’ll begin by writing a function that encapsulates the resizeObserver that we create.

    function resizeObserver () {
      // ... Do something
    }

    The easiest way to begin refactoring the ResizeObserver code is to put everything we’ve created into our resizeObserver first.

    function resizeObserver () {
      const observer = new ResizeObserver(observerFn)
    
      function observerFn (entries) {
        for (let entry of entries) {
          // Do something with entry
        }
      }
    
      const node = document.querySelector('#some-element')
      observer.observe(node);
    }

    Next, we can pass the element into the function to make it simpler. When we do this, we can eliminate the document.querySelector line.

    function resizeObserver (element) {
      const observer = new ResizeObserver(observerFn)
    
      function observerFn (entries) {
        for (let entry of entries) {
          // Do something with entry
        }
      }
    
      observer.observe(node);
    }

    This makes the function more versatile since we can now pass any element into it.

    // Usage of the resizeObserver function
    const node = document.querySelector('#some-element')
    const obs = resizeObserver(node)

    This is already much easier than writing all of the ResizeObserver code from scratch whenever you wish to use it.

    Next, it’s quite obvious that we have to pass in an observer function to the callback. So, we can potentially do this:

    // Not great
    function resizeObserver (node, observerFn) {
      const observer = new ResizeObserver(observerFn)
      observer.observe(node);
    }

    Since observerFn is always the same — it loops through the entries and acts on every entry — we could keep the observerFn and pass in a callback to perform tasks when the element is resized.

    // Better 
    function resizeObserver (node, callback) {
      const observer = new ResizeObserver(observerFn)
    
      function observerFn (entries) {
        for (let entry of entries) {
          callback(entry)
        }
      }
    
      observer.observe(node);
    }

    To use this, we can pass callback into the resizeObserver — this makes resizeObserver operate somewhat like an event listener which we are already familiar with.

    // Usage of the resizeObserver function
    const node = document.querySelector('#some-element')
    const obs = resizeObserver(node, entry => {
      // Do something with each entry
    })

    We can make the callback slightly better by providing both entry and entries. There’s no performance hit for passing an additional variable so there’s no harm providing more flexibility here.

    function resizeObserver (element, callback) {
      const observer = new ResizeObserver(observerFn)
    
      function observerFn (entries) {
        for (let entry of entries) {
          callback({ entry, entries })
        }
      }
    
      observer.observe(element);
    }

    Then we can grab entries in the callback if we need to.

    // Usage of the resizeObserver function
    // ...
    const obs = resizeObserver(node, ({ entry, entries }) => {
      // ...
    })

    Next, it makes sense to pass the callback as an option parameter instead of a variable. This will make resizeObserver more consistent with the <a href="https://splendidlabz.com/docs/utils/dom/mutation-observer" rel="noopener">mutationObserver</a> and <a href="https://splendidlabz.com/docs/utils/dom/intersection-observer" rel="noopener">intersectionObserver</a> functions that we will create in the next article.

    function resizeObserver (element, options = {}) {
      const { callback } = options
      const observer = new ResizeObserver(observerFn)
    
      function observerFn (entries) {
        for (let entry of entries) {
            callback({ entry, entries })
          }
      }
    
      observer.observe(element);
    }

    Then we can use resizeObserver like this.

    const obs = resizeObserver(node, {
      callback ({ entry, entries }) {
        // Do something ...
      }
    })

    The observer can take in an option too

    ResizeObserver‘s observe method can take in an options object that contains one property, box. This determines whether the observer will observe changes to content-box, border-box or device-pixel-content-box.

    So, we need to extract these options from the options object and pass them to observe.

    function resizeObserver (element, options = {}) {
      const { callback, ...opts } = options
      // ...
      observer.observe(element, opts);
    }

    Optional: Event listener pattern

    I prefer using callback because it’s quite straightforward. But if you want to use a standard event listener pattern, we can do that, too. The trick here is to emit an event. We’ll call it resize-obs since resize is already taken.

    function resizeObserver (element, options = {}) {
      // ...
      function observerFn (entries) {
        for (let entry of entries) {
          if (callback) callback({ entry, entries })
          else {
            node.dispatchEvent(
              new CustomEvent('resize-obs', {
                detail: { entry, entries },
              }),
            )
          }
        }
      }
    
      // ...
    }

    Then we can listen to the resize-obs event, like this:

    const obs = resizeObserver(node)
    node.addEventListener('resize-obs', event => {
      const { entry, entries } = event.detail
    })

    Again, this is optional.

    Unobserving the element

    One final step is to allow the user to stop observing the element(s) when observation is no longer required. To do this, we can return two of the observer methods:

    • unobserve: Stops observing one Element
    • disconnect: Stops observing all Elements
    function resizeObserver (node, options = {}) {
      // ...
      return {
        unobserve(node) {
          observer.unobserve(node)
        },
        
        disconnect() {
          observer.disconnet()
        }
      }
    }

    Both methods do the same thing for what we have built so far since we only allowed resizeObserver to observe one element. So, pick whatever method you prefer to stop observing the element.

    const obs = resizeObserver(node, {
      callback ({ entry, entries }) {
        // Do something ...
      }
    })
    
    // Stops observing all elements 
    obs.disconect()

    With this, we’ve completed the creation of a better API for the ResizeObserver — the resizeObserver function.

    Code snippet

    Here’s the code we’ve wrote for resizeObserver

    export function resizeObserver(node, options = {}) {
      const observer = new ResizeObserver(observerFn)
      const { callback, ...opts } = options
    
      function observerFn(entries) {
        for (const entry of entries) {
          // Callback pattern
          if (callback) callback({ entry, entries, observer })
          // Event listener pattern
          else {
            node.dispatchEvent(
              new CustomEvent('resize-obs', {
                detail: { entry, entries, observer },
              })
            )
          }
        }
      }
     
      observer.observe(node)
    
      return {
        unobserve(node) {
          observer.unobserve(node)
        },
        
        disconnect() {
          observer.disconnect()
        }
      }
    }

    Using this in practice via Splendid Labz

    Splendid Labz has a utils library that contains an enhanced version of the resizeObserver we made above. You can use it if you wanna use a enhanced observer, or if you don’t want to copy-paste the observer code into your projects.

    import { resizeObserver } from '@splendidlabz/utils/dom'
    
    const node = document.querySelector('.some-element')
    const obs = resizeObserver(node, {
      callback ({ entry, entries }) {
        /* Do what you want here */
      }
    })

    Bonus: The Splendid Labz resizeObserver is capable of observing multiple elements at once. It can also unobserve multiple elements at once.

    const items = document.querySelectorAll('.elements')
    const obs = resizeObserver(items, {
      callback ({ entry, entries }) {
        /* Do what you want here */
      }
    })
    
    // Unobserves two items at once
    const subset = [items[0], items[1]]
    obs.unobserve(subset) 

    Found this refactoring helpful?

    Refactoring is ultra useful (and important) because its a process that lets us create code that’s easy to use or maintain.

    If you found this refactoring exercise useful, you might just love how I teach JavaScript to budding developers in my Learn JavaScript course.

    In this course, you’ll learn to build 20 real-world components. For each component, we start off simple. Then we add features and you’ll learn to refactor along the way.

    That’s it!

    Hope you enjoyed this piece and see you in the next one.


    A Better API for the Resize Observer originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleInside the Frontier of AI, WebXR & Real-Time 3D: Crafting KODE Immersive
    Next Article AI-Native Product Development: 5 Pillars That Matter

    Related Posts

    News & Updates

    Development Release: Zorin OS 18 Beta

    September 19, 2025
    News & Updates

    Distribution Release: IPFire 2.29 Core 197

    September 19, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    CVE-2025-43559 – ColdFusion Code Injection Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-3878 – WooCommerce Stored Cross-Site Scripting Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-20971 – Samsung Flow Input Validation Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-7541 – Code-projects Online Appointment Booking System SQL Injection Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Highlights

    Development

    ToyMaker Uses LAGTOY to Sell Access to CACTUS Ransomware Gangs for Double Extortion

    April 26, 2025

    Cybersecurity researchers have detailed the activities of an initial access broker (IAB) dubbed ToyMaker that…

    Helldivers 2 sees the Battle for Super Earth end in victory, so here’s how it happened

    May 30, 2025

    Leading Experts in Meme Coin Development – Beleaf Technologies

    July 9, 2025

    CVE-2025-25179 – Citrix XenServer GPU Escalation of Privilege

    June 2, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.