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

      How To Prevent WordPress SQL Injection Attacks

      June 16, 2025

      This week in AI dev tools: Apple’s Foundations Model framework, Mistral’s first reasoning model, and more (June 13, 2025)

      June 13, 2025

      Open Talent platforms emerging to match skilled workers to needs, study finds

      June 13, 2025

      Java never goes out of style: Celebrating 30 years of the language

      June 12, 2025

      The 5 gadgets that got me through marathons and obstacle races (and why they work)

      June 16, 2025

      This beastly 500W charger replaced every other charger I had – with six ports to boot

      June 16, 2025

      Mac Mini won’t power on? Apple will fix it for you – for free

      June 16, 2025

      Why I’m switching to VS Code. Hint: It’s all about AI tool integration

      June 16, 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

      From Concept to Code: Final Year PHP Projects with Reports for Smart Submissions

      June 16, 2025
      Recent

      From Concept to Code: Final Year PHP Projects with Reports for Smart Submissions

      June 16, 2025

      Building Construction suppliers in India

      June 16, 2025

      Neutralinojs v6.1 released

      June 16, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Microsoft Edge’s Quiet Shift to AVIF: Why It Matters

      June 16, 2025
      Recent

      Microsoft Edge’s Quiet Shift to AVIF: Why It Matters

      June 16, 2025

      Windows 11 test builds are accidentally playing the Windows Vista startup sound

      June 16, 2025

      Leaked: ROG Xbox Ally and Xbox Ally X pre-orders set for August, launch in October

      June 16, 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 ResizeObserver 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 mutationObserver and intersectionObserver 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

    The 5 gadgets that got me through marathons and obstacle races (and why they work)

    June 16, 2025
    News & Updates

    This beastly 500W charger replaced every other charger I had – with six ports to boot

    June 16, 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

    I thought MacOS 15.4.1 was a minor update until it made my iMac better in 4 big ways

    News & Updates

    These upcoming headphones from EarFun are an impressive feat at a cheap price

    News & Updates

    CVE-2025-46257 – BdThemes Element Pack Pro CSRF Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    The AI for Science Forum: A new era of discovery

    Artificial Intelligence

    Highlights

    News & Updates

    Capcom breaks all-time profit records with 10% income growth after Monster Hunter Wilds sold over 10 million copies in a month

    May 15, 2025

    Capcom has issued a press release stating that the company has achieved record-breaking sales and…

    Microsoft is making several AI features accessible across Windows 11 & Copilot + PCs

    May 8, 2025

    World’s First 60 Seconds AI Video Maker: The Future is Here?

    April 17, 2025

    CVE-2025-46329 – Snowflake libsnowflakeclient Sensitive Information Logging

    April 29, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

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