Tips to Avoid Layout Thrashing

Layout thrashing happens when JavaScript accesses certain properties that require the browser to recompute the layout of the web page. This process is costly because the browser needs to recalculate the size and position of elements based on their styles and content.

The following JavaScript operations can trigger layout thrashing:

  1. Reading Layout Properties: Accessing properties like offsetWidth, offsetHeight, clientWidth, clientHeight, getComputedStyle, or scrollWidth can trigger layout recalculations.
  2. Modifying Styles and Dimensions: Changing styles (e.g., element.style.width) or adding/removing DOM elements may cause layout changes.

To minimize layout thrashing and improve your web application’s performance, follow these best practices:

  1. Batch DOM Read and Write Operations: Minimize the number of times you read layout-affecting properties (offsetWidth, offsetHeight, etc.) and write to the DOM. Instead, batch these operations together.
    // Bad practice (triggers layout thrashing) 
    const width = element.offsetWidth;
    const height = element.offsetHeight; 
    
    // Better approach (batch reads and writes)
    const styles = getComputedStyle(element);
    const width = element.offsetWidth; // No thrashing here
    const height = element.offsetHeight; // No thrashing here 
    element.style.width = (width + 10) + 'px'; // Apply styles once
  2. Use Classes for Style Changes: Instead of modifying individual style properties directly, leverage CSS classes and toggle them on/off for style changes. This reduces the number of layout recalculations.
    // Bad practice (triggers layout thrashing)
    element.style.width = (element.offsetWidth + 10) + 'px';
    
    // Better approach (uses CSS classes)
    element.classList.add('expanded');
  3. Cache Layout Properties: Store layout-affecting properties in variables to avoid repetitive calculations.
    // Bad practice (repeated layout calculations)
    for (let i = 0; i < elements.length; i++) {
      const width = elements[i].offsetWidth; // Layout thrashing 
      // Use width...
    }
    
    // Better approach (caches layout properties)
    const widths = [];
    for (let i = 0; i < elements.length; i++) {
      widths[i] = elements[i].offsetWidth; // No thrashing 
    // Use widths[i]...
    }
  4. Optimize CSS: Optimize your CSS to minimize layout changes caused by style modifications. Avoid forced synchronous layouts by ensuring efficient CSS rules.

Leave a Reply