How to configure lazy loading
Overview
This guide demonstrates how to build a web element that lazy-loads its content only when it becomes visible in the viewport.
Lazy loading allows widgets to load only when they are needed. Implementing lazy loading provides several key benefits:
- Reduced initial page load time and bandwidth usage
- Lower memory consumption for off-screen content
- Improved performance metrics like Time to Interactive
- Better user experience, especially on mobile devices
How it works
- A TradingView widget is wrapped inside the HTML
<template>
tag, so the element is not rendered or executed immediately. - The
<template>
content is placed inside a customlazy-load
element that handles lazy loading. - The Intersection Observer API detects when the element becomes visible.
- When visible, the element clones the template content and adds it to the DOM.
- Scripts inside the template are then executed.
Follow the steps below to implement a lazy-loading element.
1. Define the element in JavaScript
Create a new custom HTML element using JavaScript. In this example, we define a <lazy-load>
element by extending the built-in HTMLElement
class.
The <lazy-load>
element uses the IntersectionObserver
API to detect when it enters the viewport. This allows content to be loaded only when the user scrolls near it.
You can place the code below in a separate file, such as lazy-load.js
.
class LazyLoad extends HTMLElement { constructor() { super(); this._hasLoaded = false; this._observer = null; }
connectedCallback() { // Set up 'IntersectionObserver' interface to monitor when the element becomes visible this._observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting && !this._hasLoaded) { this._loadContent(); this._hasLoaded = true; this._observer.disconnect();
// Hide the scroll indicator document.querySelector(".scroll-indicator").style.display = "none"; } }); }, { rootMargin: "50px", threshold: 0.1, } );
this._observer.observe(this); }
disconnectedCallback() { if (this._observer) { this._observer.disconnect(); } }
_loadContent() { const template = this.querySelector("template"); if (template) { // Clone the template content and append it const content = template.content.cloneNode(true); // Remove the template template.remove(); this.appendChild(content);
// Manually create and execute any scripts content.querySelectorAll("script").forEach((oldScript) => { const newScript = document.createElement("script");
// Copy all attributes Array.from(oldScript.attributes).forEach((attr) => { newScript.setAttribute(attr.name, attr.value); });
// Copy inline script content newScript.textContent = oldScript.textContent;
// Replace the old script with the new one oldScript.parentNode.replaceChild(newScript, oldScript); }); } }}
// Register the custom elementcustomElements.define("lazy-load", LazyLoad);
2. Define the widget in HTML
- Wrap your widget inside the
<template>
tag. This prevents the widget from rendering or executing immediately. - Wrap
<template>
in a custom<lazy-load>
element. This controls when the widget is actually loaded.
<!-- Lazy-loading element --><lazy-load> <template> <!-- TradingView Widget BEGIN --> <div class="tradingview-widget-container"> <div class="tradingview-widget-container__widget"></div> <div class="tradingview-widget-copyright"> <a href="https://www.tradingview.com/" rel="noopener nofollow" target="_blank" ><span class="blue-text" >Track all markets on TradingView</span ></a > </div> <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-mini-symbol-overview.js" async > { "symbol": "FX:EURUSD", "width": 350, "height": 220, "locale": "en", "dateRange": "12M", "colorTheme": "light", "isTransparent": false, "autosize": false, "largeChartUrl": "" } </script> </div> <!-- TradingView Widget END --> </template></lazy-load>
3. Load the script
To make the <lazy-load>
element work, load the lazy-load.js
script in your HTML file using the <script>
element.
<script src="./lazy-load.js"></script>
It is recommended that this script is included before any <lazy-load>
elements are rendered, typically inside the <head>
element.
View demo
View the full working demo below. Open your browser’s DevTools and switch to the Network tab, you’ll notice that the widget only loads when it enters the viewport.