npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lazy-load-image-lit

v1.1.5

Published

A lightweight, framework-agnostic lazy loading image web component built with Lit

Downloads

28

Readme

lazy-load-image-lit

License: MIT npm version npm downloads

A lightweight, framework-agnostic lazy loading image component built with Lit Element. Load images only when they're visible to improve page performance and user experience.

Live Demo

Why I Built This

I was inspired by the popular react-lazy-load-image-component, which works great but is limited to React applications. I wanted to create something with the same powerful lazy loading capabilities but that would work universally across all frameworks and vanilla JavaScript.

By building with Lit Element, this component:

  • Works in any framework (React, Vue, Angular, Svelte) or no framework at all
  • Stays lightweight with minimal dependencies
  • Achieves excellent performance through efficient rendering
  • Provides a clean, standards-based API

Features

Performance Focused

Images load only when they enter (or approach) the viewport, significantly reducing initial page load time and saving bandwidth.

Progressive Enhancement

Uses IntersectionObserver API for modern browsers with intelligent fallback to optimized scroll events for older browsers.

Visual Transitions

Smooth loading effects with multiple options:

  • Blur Effect: Starts with a blurred placeholder that sharpens when loaded.
  • Black and White Effect: Shows a grayscale version that transitions to full color.

Highly Configurable

  • Control threshold distance for preloading images.
  • Choose between debounce or throttle for scroll performance optimization.
  • Configure with visible-by-default option for above-the-fold content.
  • Set specific dimensions or use responsive sizing.

Responsive & Mobile-Friendly

Works seamlessly across all device sizes and adapts to different viewport dimensions.

Zero External Dependencies

Only depends on Lit, which is included in the bundle.

Framework Agnostic

Works natively in any environment:

  • Vanilla HTML/JS projects.
  • React applications with proper event handling.
  • Vue.js with native custom element support.
  • Angular with CUSTOM_ELEMENTS_SCHEMA.
  • Any other modern framework.

Peer Dependency Required

Important: This package requires lit as a peer dependency. You must install it in your project:

npm install lit

Installation

npm install lazy-load-image-lit

Basic Usage

<!-- Import the component -->
<script type="module" src="node_modules/lazy-load-image-lit/dist/lazy-load-image-lit.es.js"></script>

<!-- Use it in your HTML -->
<lazy-img
  src="high-quality-image.jpg"
  placeholderSrc="low-quality-thumbnail.jpg"
  effect="blur"
  threshold="200"
></lazy-img>

Framework Examples

React

import React, { useRef, useEffect } from 'react';
import 'lazy-load-image-lit';

function MyImage({ src, placeholder }) {
  const imgRef = useRef(null);
  
  useEffect(() => {
    // Use event listener for React integration
    if (imgRef.current) {
      imgRef.current.addEventListener('image-loaded', (e) => {
        console.log('Image loaded in React!', e.detail);
      });
    }
  }, []);

  return (
    <lazy-img
      ref={imgRef}
      src={src}
      placeholderSrc={placeholder}
      effect="blur"
    ></lazy-img>
  );
}

Vue

<template>
  <lazy-img
    :src="imageUrl"
    :placeholderSrc="placeholderUrl"
    @image-loaded="onImageLoaded"
  ></lazy-img>
</template>

<script>
import 'lazy-load-image-lit';

export default {
  methods: {
    onImageLoaded(e) {
      console.log('Image loaded in Vue!', e.detail);
    }
  }
}
</script>

Angular

// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import 'lazy-load-image-lit';

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA] // Required for custom elements
})
<!-- component.html -->
<lazy-img
  [attr.src]="image.src"
  [attr.placeholderSrc]="image.placeholder"
  (image-loaded)="onImageLoaded($event)"
></lazy-img>

Properties & Attributes

| Property | Type | Default | Description | Available Options | |----------------------|---------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------| | src | String | '' | The URL of the main image to be lazy-loaded. When the image is about to enter the viewport, this is set as the src of the <img> element. | Any valid image URL | | placeholderSrc | String | '' | The URL of the placeholder image shown before the main image loads. This is always rendered until the main image is loaded and visible. | Any valid image URL | | effect | String | 'blur' | Visual effect applied to the image during loading. 'blur' applies a blur to the placeholder, 'black-and-white' shows a grayscale effect. The effect is removed when the main image loads. | 'blur', 'black-and-white' | | threshold | Number | 0 | Distance in pixels from the viewport or scroll container at which the image should start loading. For IntersectionObserver, this is used as rootMargin. For scroll/resize fallback, the image loads when it is within this many pixels of entering the visible area, allowing for preloading before the image is actually visible. | Any number (e.g., 200 for 200px) | | useIntersectionObserver | Boolean | true | If true, uses the IntersectionObserver API for efficient lazy loading. If false, falls back to scroll/resize event listeners for visibility detection. | true, false | | visibleByDefault | Boolean | false | If true, the image loads immediately without lazy loading. Useful for above-the-fold images. If false, lazy loading is enabled. | true, false | | delayMethod | String | 'debounce' | Method for handling scroll/resize events: 'debounce' waits for a pause in events, 'throttle' limits event frequency. Only used when not using IntersectionObserver. | 'debounce', 'throttle' | | delayTime | Number | 300 | Time in milliseconds for throttling or debouncing scroll/resize events. Controls how often visibility checks are performed. | Any positive number | | width | Number | 0 | Width of the image in pixels. Passed directly to the <img> element. If 0, the attribute is omitted and the image uses its natural width or CSS. | Any valid pixel value | | height | Number | 0 | Height of the image in pixels. Passed directly to the <img> element. If 0, the attribute is omitted and the image uses its natural height or CSS. | Any valid pixel value | | imgStyle | String | '' | Additional inline styles to apply to the <img> element. Useful for custom styling or responsive images. | Any valid CSS style string |

Events

| Event Name | When It Fires | Data Provided | |------------|---------------|--------------| | image-loaded | When the main image has finished loading | Original image load event in the detail property |

Window Scroll

ScreenRecording2025-06-16at20 29 45-ezgif com-optimize

Vertical-Container

ScreenRecording2025-06-16at20 32 01-ezgif com-optimize

Horizontal Scroll

horizontal-ezgif com-optimize

Advanced Configuration

Preloading Images Just Before Scrolling

<!-- Start loading when image is 500px before entering viewport -->
<lazy-img 
  threshold="500" 
  src="large-image.jpg" 
  placeholderSrc="thumbnail.jpg"
></lazy-img>

Controlling Scroll Event Performance

By default, the lazy loading component uses the debounce method for handling scroll and resize events. This means images are only checked and loaded after scrolling has paused for a short period, reducing unnecessary work and improving performance. You can also use throttle if you prefer more frequent checks.

How it works:

  • When you scroll quickly through a long list of images, debounce ensures that only the images currently in (or near) the viewport are loaded. For example, if you scroll rapidly to the bottom, only the last few images will load, and images in between are skipped until you scroll back up.
  • As you scroll back up, images will load one by one as they come into view, rather than all at once. This makes the experience smoother and more efficient, especially for pages with many images.

Example (using debounce):

<lazy-img 
  delayMethod="debounce" 
  delayTime="150"
  src="image.jpg" 
  placeholderSrc="small.jpg"
></lazy-img>

This approach helps keep your page fast and responsive, even with a large number of images, by only loading what the user is actually about to see.

Common Errors

All Images Load at Once (Scroll Container Issue)

A common issue when using this package is that all images load immediately, even if they are not visible. This usually happens because the package first checks for the nearest parent element with overflow: auto or overflow: scroll to determine which container should be used for lazy loading.

If you set overflow: auto or overflow: scroll on a parent element that isn't actually scrollable (for example, if it doesn't have a fixed height or enough content to scroll), the component may think all images are in view and load them right away. This defeats the purpose of lazy loading.

Best Practice:

  • Only add overflow: auto or overflow: scroll to a parent container if you really need a scrollable area (e.g., a div with a fixed height and lots of images inside).
  • If you don't need scrolling, avoid setting these overflow properties. Let the package use the window as the scroll container, so images are only loaded as they enter the viewport.

This small adjustment can make a big difference in how well lazy loading works in your app!