Technical Interview Checklist - Web Edition

Reflow and Repaint

Reflow and repaint are two major processes that occur when a web browser processes the DOM and renders the screen. These two processes are distinct and can significantly impact the browser's rendering performance.

Reflow

  • Definition: Reflow is the process that occurs when the layout of a web page changes. When the size, position, or shape of an element changes, the browser recalculates the DOM tree to determine the placement of elements. This process can rearrange all elements in the layout.
  • Causes: The following actions can trigger a reflow:
      • Adding or removing DOM elements
      • Changing CSS styles (e.g., width, height, margin, padding, etc.)
      • Resizing the window
      • Changing the position of an element (e.g., changes to the position property)
      • Changing the font size
  • Performance Impact: Reflow is a relatively expensive operation. Since many elements on the page can be affected, it can impact performance. When a reflow occurs, the browser must recalculate the layout of all descendant elements of the affected element.

Repaint

  • Definition: Repaint occurs when only the visual appearance of an element changes. When visual properties like color, background, or text color are altered, the browser redraws the element. However, the layout itself is not affected.
  • Causes: Repaint occurs in the following scenarios:
      • Changing the background color of an element
      • Changing the text color
      • Changing the src of an image or video
  • Performance Impact: Repaint is less costly than reflow, but many repaints can still affect overall performance. Repaint proceeds relatively quickly since layout calculations are not required, but frequent repaints can degrade rendering performance.

Optimization Methods

  • Optimizations to Reduce Reflow:
      • Apply changes all at once instead of directly accessing the DOM.
      • Change CSS classes or styles at once, causing reflow only when necessary.
      • Consider using the visibility or opacity properties if layout changes are not needed.
  • Optimizations to Reduce Repaint:
      • Change the minimum number of CSS properties.
      • Group CSS property changes to handle them in a single repaint.
  • If modifying the layout or elements during scroll events triggers reflow or repaint, optimization can be achieved using IntersectionObserver.

IntersectionObserver

IntersectionObserver is an API that allows web browsers to asynchronously observe whether an element enters or exits the viewport or a specific parent element. Using this API makes it easier to detect whether elements are visible on screen based on scrolling, which is more performance-efficient than directly using scroll events.

Key Concepts of IntersectionObserver

  1. Asynchronous Observation: IntersectionObserver can asynchronously check the intersection status between the target element and the viewport or specific element boundaries.
  2. Callback Function: A callback function is triggered every time the element crosses the observed boundaries.
  3. Options: When observing, you can set the root element (default is the viewport), margin for boundaries, and intersection ratio.

Replacing Event Listeners Related to Reflow

The scroll event often causes performance issues because it frequently triggers reflow. Reflow is the process by which the browser recalculates the layout when an element's position or size changes, and frequent occurrences can lead to performance degradation. The scroll event can cause reflow to occur often based on scroll positions.

Previously, scroll events were frequently used to detect if elements were visible on the screen, which posed performance problems.

Using Scroll Events (Inefficient)

window.addEventListener('scroll', () => {
  let target = document.querySelector('.target-element');
  let bounding = target.getBoundingClientRect();

  if (
    bounding.top >= 0 &&
    bounding.left >= 0 &&
    bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
    bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
  ) {
    console.log('Element is in view!');
  } else {
    console.log('Element is out of view.');
  }
});

This code affects performance because it calls getBoundingClientRect() to calculate the element's position every time the scroll event occurs.

Using IntersectionObserver Instead (Efficient)

let target = document.querySelector('.target-element');

let observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      console.log('Element is in view!');
    } else {
      console.log('Element is out of view.');
    }
  });
});

// Start observing the element
observer.observe(target);

This code uses IntersectionObserver to detect when elements appear on the screen without directly handling scroll events. The browser efficiently calculates the intersection status between the viewport and elements, reducing unnecessary reflow or layout recalculations. By using IntersectionObserver instead of the scroll event, you can improve performance by leveraging the browser's optimized mechanisms.

Browser Rendering Order

  1. HTML Parsing and DOM Creation (Document Object Model)
  • When the browser receives the HTML file from the server, it reads it line by line to create the DOM tree.
  • The DOM tree represents the logical structure of the HTML document in a tree format.
  • Each HTML tag becomes a node in the DOM, which serves as the basis for subsequent rendering processes.
<html>
  <body>
    <h1>Hello World</h1>
    <p>This is a paragraph.</p>
  </body>
</html>

This HTML transforms into the following DOM tree:

Document
└── html
    └── body
        ├── h1
        └── p
  1. CSS Parsing and CSSOM Creation (CSS Object Model)
  • The CSS included in the HTML file is also parsed. The CSS parser reads it and structures the style rules into the CSSOM (CSS Object Model).
  • CSSOM defines the styles to be applied to each element. The CSSOM tree combines with the DOM tree to determine how elements will be rendered on the screen.
body {
  font-size: 16px;
}
h1 {
  color: blue;
}

This transforms into the following CSSOM tree:

CSSOM
├── body { font-size: 16px; }
└── h1 { color: blue; }

3. Render Tree Creation

  • The DOM tree and CSSOM tree combine to create the Render Tree.
  • The render tree includes only the elements that will be displayed on the screen, meaning hidden elements, like those with display: none, are not included.
  • The render tree determines how each element will be rendered on the screen.
Render Tree
├── body
└── h1 (color: blue, font-size: 16px)
  1. Layout Calculation (Layout/Reflow)
  • This step calculates the position and size of each element based on the render tree. This process is referred to as layout or reflow.
  • The browser calculates where each element will be placed on the page according to the screen size and CSS properties.
  • At this stage, the coordinates and size of each element are determined in pixels.

5. Painting

  • Once the layout is complete, the browser prepares the content to be drawn on the screen. This process is called painting, where the visual properties of elements, such as colors, shadows, and background images, are processed.
  • The browser determines which images, texts, and borders to draw on the screen according to each element's style properties.

6. Compositing

  • In complex pages, multiple layers must be processed simultaneously. For instance, elements with applied animations or elements stacked on top of others using z-index can exist.
  • The browser divides these elements into layers, rendering each layer individually before compositing them into a final output on the screen.
  • This step may utilize GPU acceleration when necessary.

Summary of the Browser Rendering Process

  1. HTML Parsing → DOM Tree Creation
  2. CSS Parsing → CSSOM Tree Creation
  3. DOM + CSSOM → Render Tree Creation
  4. Layout Calculation (Layout/Reflow)
  5. Painting
  6. Compositing

JavaScript Processing and Rendering Interruption

  • JavaScript can pause DOM parsing. If a script is placed within a <script> tag, the browser must execute the JavaScript before completing the DOM tree, causing a temporary halt in rendering.
  • To prevent JavaScript files from blocking DOM parsing and rendering, use the defer or async attributes:
      • defer: Executes the script after DOM parsing is complete.
      • async: Loads the script asynchronously and executes it as soon as parsing is complete.

Stacking Context

A stacking context determines how HTML elements are stacked based on the z-axis (z-index) on the screen. This rule defines how elements overlap on the screen and which elements are placed above or below others.

In simple terms, stacking context can be seen as a "layer system" that the browser uses to decide how to position each element based on the z-axis (depth) in the 2D plane of a web page.

1. Stacking Order

Each element is stacked primarily based on its z-index value

. Elements with a higher z-index will appear on top of elements with a lower z-index.

Default Stacking Order:

  1. Background and Borders (elements with no position set)
  2. Positioned Elements (elements with position: relative, absolute, or fixed)
  3. Floating Elements (elements with float set)
  4. Non-positioned Elements (elements without position or float)
  5. Elements with Negative z-index
  6. Fixed Elements (elements with position: fixed)
  7. Local Stacking Contexts (elements creating their stacking contexts)

2. Creating a New Stacking Context

Certain CSS properties can trigger the creation of a new stacking context:

  • position with z-index (when z-index is not auto)
  • opacity (any value less than 1)
  • transform (with any value other than none)
  • filter (with any value other than none)
  • perspective (with any value other than none)
  • clip-path (with any value other than none)
  • mask (with any value other than none)

3. Example of Stacking Context

/* Parent with z-index creating a new stacking context */
.parent {
  position: relative;
  z-index: 10;
}

/* Child with a higher z-index */
.child {
  position: relative;
  z-index: 20; /* This will be above other children with lower z-index */
}

/* Child with a lower z-index */
.child-low {
  position: relative;
  z-index: 5; /* This will be below the .child element */
}

/* A sibling with a lower z-index than parent stacking context */
.sibling {
  position: absolute;
  z-index: 0; /* This will be below all children of .parent */
}

In this example, the child with a z-index of 20 will be placed above the child with a z-index of 5, but both will be positioned above .sibling due to the new stacking context created by .parent.

Conclusion

Understanding how reflow, repaint, IntersectionObserver, and the browser rendering process work is crucial for optimizing the performance of web applications. Additionally, recognizing stacking contexts is vital to manage how elements overlap on the screen.

Focusing on optimizing rendering performance will ensure a smoother user experience. By employing efficient practices, we can reduce unnecessary reflow and repaint cycles while effectively using APIs such as IntersectionObserver for better performance in our applications.


This overview should provide a solid foundation for your upcoming frontend developer interview. Be sure to understand the concepts well, and feel free to reach out for any further clarifications or practice questions!

← Go home