Skip to content

useLazyLoad ​

useLazyLoad lazily loads an image once it scrolls into the viewport.

It is built on top of the Intersection Observer API. The controller element is expected to be an <img> whose real source is provided through a data-[identifier]-src attribute. The image is only fetched and assigned to the src attribute once the element becomes visible.

It adds two new behaviors to your Stimulus controller:

  • loading(src) triggered when the image starts loading.
  • loaded(src) triggered when the image has finished loading.

Reference ​

javascript
useLazyLoad(controller, options)

controller : a Stimulus Controller (usually 'this')

options : an optional IntersectionObserverInit object (root, rootMargin, threshold). When extending LazyLoadController the default is { rootMargin: '10%' }.

returns : [observe, unobserve], the two functions used to start and stop observing the element.

This module also adds the following readable state properties to your controller:

PropertyDescription
isLoadingtrue while the image is being fetched.
isLoadedtrue once the image has finished loading.

Usage ​

The controller element must be an <img> tag and the image URL must be passed via the data-[identifier]-src attribute (it is read through Stimulus' data.get('src')). If the attribute is missing, nothing happens.

html
<img data-controller="image" data-image-src="https://example.com/photo.jpg" alt="A lazily loaded photo">

Composing

js
import { Controller } from '@hotwired/stimulus'
import { useLazyLoad } from 'stimulus-use'

export default class extends Controller {
  connect() {
    useLazyLoad(this, { rootMargin: '10%' })
  }

  loading(src) {
    // triggered when the image starts loading
  }

  loaded(src) {
    // triggered when the image has finished loading
  }
}

Extending a controller

js
import { LazyLoadController } from 'stimulus-use'

export default class extends LazyLoadController {
  loading(src) {
    // triggered when the image starts loading
  }

  loaded(src) {
    // triggered when the image has finished loading
  }
}