Lazy loading


Covered in this doc

  • Lazy loading brief
  • Handling lazy loading with Percy

This document describes how Percy handles lazy loading while taking screenshots for Visual Regression Testing.
Primary ways to do lazy loading, as per MDN docs and CSS-Tricks.

Main reason why mobile websites use lazy-loading is to save on processing power by not rendering an element before it enters into the mobile viewport.
There are two basic issues observed due to this.

  • Asset Capture
  • Full page view (Stitching issues)

Asset Capture

Certain assets are only fetched on lazy-loading and if the user does not scroll page till the bottom during the snapshot capture phase, these URLs won’t be captured, hence returning 404 while rendering on Percy infrastructure, as Percy infra cannot resolve it.

Full page view (Stitching issues)

In Percy infrastructure, we render DOM, calculate the height of the page, scroll till the end of the page and take screenshot for each screen scrolled.

When there is no specific width and height given to lazy loaded elements, during scrolling these elements height will change according to DOM.
This cascades other elements to go further down the DOM, and also increases the DOM’s height as well.

Possible Solution

The solution lies in the fact that "lazy loading transformations must be done on the DOM before using snapshot function from Percy SDK".

You can implement a solution of your preference to get the above job done. Mentioned below is one recommended approach which can be used to achieve the same.

Scroll till the end of the DOM before using Percy SDK snapshot function. In this case, DOM would have already replaced the src with value from data-src and also manipulated the classes / attributes accordingly.

The tricky part here is to write a small script that will make sure all lazy loading transformations are done on the DOM before using snapshot function from Percy SDK.
Please use below code sample for your reference & feel free to modify as per your language & framework requirements.

const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('', { waitUntil: 'networkidle' });
  await percySnapshot(page, 'js disabled your domain page');

  // Scrolling for 100px and sleeping for 100ms till page is scrolled
  // If your page has infite scroll, then try restricting your scrolls to max 32,000 pixels
  await page.evaluate(async () => {
    const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
    for (let i = 0; i < document.body.scrollHeight; i += 100) {
      window.scrollTo(0, i);
      await delay(100);
  await percySnapshot(page, 'js disabled your domain sleep scroll');

When this is implemented properly, then both asset capture and full page issues are resolved.