or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Element Resize Detector

Element Resize Detector is a JavaScript library that provides optimized cross-browser resize detection for DOM elements. It offers up to 37x better performance than related approaches through two detection strategies: scroll-based (recommended) and object-based.

Package Information

  • Package Name: element-resize-detector
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install element-resize-detector

Core Imports

Node.js/CommonJS:

var elementResizeDetectorMaker = require("element-resize-detector");

ES modules (if using with a bundler):

import elementResizeDetectorMaker from "element-resize-detector";

Browser (via script tag):

<script src="node_modules/element-resize-detector/dist/element-resize-detector.min.js"></script>

This creates a global function elementResizeDetectorMaker.

Basic Usage

var elementResizeDetectorMaker = require("element-resize-detector");

// Create detector with default options
var erd = elementResizeDetectorMaker();

// Listen to resize events
erd.listenTo(document.getElementById("test"), function(element) {
    var width = element.offsetWidth;
    var height = element.offsetHeight;
    console.log("Size: " + width + "x" + height);
});

// High performance setup
var erdFast = elementResizeDetectorMaker({
    strategy: "scroll"
});

// Listen to multiple elements
var elements = document.querySelectorAll(".resizable");
erdFast.listenTo(elements, function(element) {
    // Handle resize for each element
});

// Cleanup when done
erd.uninstall(document.getElementById("test"));

Architecture

Element Resize Detector is built around several key components:

  • Detection Strategies: Two approaches for detecting size changes - scroll-based (high performance) and object-based (legacy compatibility)
  • State Management: Internal element state tracking during installation, detection setup, and cleanup phases
  • Event System: Listener registration, callback synchronization, and cleanup management
  • Cross-Document Support: Initialization system for elements in iframes and other document contexts
  • Automatic Fallback: Browser detection and automatic strategy selection for optimal compatibility

Capabilities

Factory Function

Creates an element resize detector instance with optional configuration.

/**
 * Creates an element resize detector instance
 * @param {Options} options - Optional configuration object
 * @returns {ElementResizeDetector} Detector instance with public API methods
 */
function elementResizeDetectorMaker(options);

interface ElementResizeDetector {
    listenTo(options: Options, elements: Element | Element[] | NodeList, listener: (element: Element) => void): void;
    listenTo(elements: Element | Element[] | NodeList, listener: (element: Element) => void): void;
    removeListener(element: Element, listener: (element: Element) => void): void;
    removeAllListeners(element: Element): void;
    uninstall(elements: Element | Element[] | NodeList): void;
    initDocument(targetDocument: Document): void;
}

Listen to Elements

Makes elements resize-detectable and starts listening to resize events.

/**
 * Makes elements resize-detectable and starts listening to resize events
 * @param {ListenToOptions} options - Options that override global options for this call (includes onReady callback)
 * @param {Element|Element[]|NodeList} elements - Single element, array of elements, or element collection
 * @param {Function} listener - Callback executed for each resize event, receives element as argument
 */
listenTo(options, elements, listener);

/**
 * Overload without options parameter
 * @param {Element|Element[]|NodeList} elements - Single element, array of elements, or element collection  
 * @param {Function} listener - Callback executed for each resize event, receives element as argument
 */
listenTo(elements, listener);

Usage Example:

// With options
erd.listenTo({ callOnAdd: false }, element, function(el) {
    console.log("Element resized:", el);
});

// Without options
erd.listenTo(element, function(el) {
    console.log("Element resized:", el);
});

// Multiple elements
erd.listenTo([element1, element2], function(el) {
    console.log("Element resized:", el);
});

// With onReady callback
erd.listenTo({
    onReady: function() {
        console.log("All elements are ready for detection");
        // Safe to trigger size changes here
    }
}, elements, function(el) {
    console.log("Element resized:", el);
});

Remove Specific Listener

Removes a specific listener from an element.

/**
 * Removes a specific listener from an element
 * @param {Element} element - DOM element to remove listener from
 * @param {Function} listener - Specific listener function to remove
 */
removeListener(element, listener);

Remove All Listeners

Removes all listeners from an element without completely removing the detector.

/**
 * Removes all listeners from an element without completely removing the detector
 * @param {Element} element - DOM element to remove all listeners from
 */
removeAllListeners(element);

Uninstall Detector

Completely removes the detector and all listeners from elements.

/**
 * Completely removes the detector and all listeners from elements
 * @param {Element|Element[]|NodeList} elements - Elements to uninstall detector from
 */
uninstall(elements);

Initialize Document

Initializes the detector for elements in another document (e.g., iframe).

/**
 * Initializes the detector for elements in another document (e.g., iframe)
 * @param {Document} targetDocument - Document object to initialize for element detection
 */
initDocument(targetDocument);

Usage Example:

// Initialize for iframe content
var iframe = document.getElementById("myFrame");
erd.initDocument(iframe.contentDocument);

// Now you can listen to elements in the iframe
var iframeElement = iframe.contentDocument.getElementById("resizable");
erd.listenTo(iframeElement, function(element) {
    console.log("Iframe element resized");
});

Configuration Options

Global Options

Options passed to elementResizeDetectorMaker(options):

interface Options {
    /** Detection strategy to use. "scroll" is recommended for performance */
    strategy?: "object" | "scroll";
    
    /** Whether listeners should be called when added (guarantees initial call) */
    callOnAdd?: boolean;
    
    /** Enable debug logging for the listenTo method */
    debug?: boolean;
    
    /** Custom ID handler for generating and managing element IDs */
    idHandler?: IdHandler;
    
    /** Custom reporter for logs/warnings/errors. Set to false for quiet mode */
    reporter?: Reporter | false;
    
    /** Custom batch processor for handling resize events */
    batchProcessor?: BatchProcessor;
    
    /** Adds !important to injected CSS rules to avoid conflicts */
    important?: boolean;
}

interface IdHandler {
    /** Gets the resize detector id of the element */
    get(element: Element, readonly?: boolean): string;
    /** Generate and sets the resize detector id of the element */
    set(element: Element): string;
}

interface Reporter {
    log(message: string): void;
    warn(message: string): void;
    error(message: string): void;
}

Default Values:

{
    strategy: "object",
    callOnAdd: true,
    debug: false,
    idHandler: /* internal default */,
    reporter: /* internal default */,
    batchProcessor: /* internal default */,
    important: false
}

listenTo Options

Options that can be passed to individual listenTo calls to override global options:

interface ListenToOptions {
    /** Override global callOnAdd setting for this listener */
    callOnAdd?: boolean;
    
    /** Override global debug setting for this listener */
    debug?: boolean;
    
    /** Callback invoked when all elements are ready for detection */
    onReady?: () => void;
}

Detection Strategies

Scroll Strategy

  • Strategy: "scroll"
  • Performance: Ultra-fast (recommended)
  • Browser Support: Modern browsers only
  • Automatic Fallback: Library automatically detects unsupported browsers and switches to object strategy with warnings:
    • Legacy Opera: "Scroll strategy is not supported on legacy Opera. Changing to object strategy."
    • IE9: "Scroll strategy is not supported on IE9. Changing to object strategy."
var erd = elementResizeDetectorMaker({
    strategy: "scroll" // May automatically fallback to object strategy
});

Object Strategy

  • Strategy: "object"
  • Performance: Standard performance
  • Browser Support: Works on legacy browsers including IE8/9 and Legacy Opera
var erd = elementResizeDetectorMaker({
    strategy: "object"
});

Browser Compatibility

  • Modern Browsers: Full support with scroll strategy
  • Legacy Support: Object strategy supports IE8/9, Opera 12
  • Automatic Fallback: Library automatically selects appropriate strategy based on browser

Error Handling

The library throws specific errors for various conditions:

Factory Function Errors:

  • Invalid strategy: Error: Invalid strategy name: [strategyName] when an unsupported strategy is specified

listenTo Function Errors:

  • Missing elements: Error: At least one element required. when no elements are provided
  • Missing listener: Error: Listener required. when no listener function is provided
  • Invalid element types: Invalid arguments. Must be a DOM element or a collection of DOM elements. (via reporter.error)

Example Error Handling:

try {
    var erd = elementResizeDetectorMaker({
        strategy: "invalid-strategy"
    });
} catch (error) {
    console.error("Strategy error:", error.message);
    // Fallback to default strategy
    erd = elementResizeDetectorMaker();
}

// The library will automatically handle invalid elements via reporter
erd.listenTo("not-an-element", function() {}); // Logs error, doesn't throw

The reporter system handles warnings and errors during operation, and automatic strategy fallback occurs for unsupported browsers.

Performance Characteristics

  • Up to 37x faster than related approaches
  • Scroll strategy provides ultra performance
  • Object strategy for broader compatibility
  • Batched processing of resize events for efficiency

Important Caveats

  1. Position Changes: If the element has position: static it will be changed to position: relative. Any unintentional top/right/bottom/left/z-index styles will therefore be applied and absolute positioned children will be positioned relative to the element.

  2. DOM Injection: A hidden element will be injected as a direct child to the element for detection purposes.

  3. Document Initialization: For elements inside iframes or other documents, you must call initDocument() with the target document before listening to elements in that document.

  4. Element State Management: The library maintains internal state for each element during the installation process:

    • Elements transition through "busy" state during installation to prevent concurrent setup
    • Size changes detected during installation automatically trigger resize events after completion
    • Multiple listenTo calls for the same element are synchronized and share installation completion callbacks

Advanced Usage

Iframe Support

When working with iframes, initialize the iframe's document:

var iframe = document.getElementById("myFrame");

// Initialize when iframe loads
iframe.onload = function() {
    erd.initDocument(iframe.contentDocument);
    
    // Now you can listen to elements inside the iframe
    var iframeElement = iframe.contentDocument.getElementById("resizable");
    erd.listenTo(iframeElement, function(element) {
        console.log("Iframe element resized");
    });
};

CSS Conflicts

If you experience CSS conflicts, use the important option:

var erd = elementResizeDetectorMaker({
    important: true  // Adds !important to injected CSS rules
});