Lazy Image

Lazy Image is a lightweight image loading utility for FrontAlign. It keeps real image URLs out of src until the image is close to the viewport, then loads them automatically from data-src.

Use Lazy Image for:

  • Gallery images and photo grids
  • Blog thumbnails and article cards
  • Product images and ecommerce sections
  • Hero and landing page media
  • Images rendered after async data fetches
  • Any image that should not load before it is needed

FrontAlign Lazy Image combines native browser observers with a small runtime layer. The markup only needs an img element with data-src; the JavaScript layer handles viewport detection, preload testing, shimmer removal, loaded state, and error fallback UI.

Getting Started

Lazy Image does not need a component wrapper or fa-component attribute. When FrontAlign is started from NPM or CDN, the runtime automatically observes img[data-src] images.

The only required attribute is data-src.

<img
  data-src="/images/gallery/photo-1.jpg"
  alt="Mountain landscape"
  width="800"
  height="500"
/>

After new FrontAlign() runs, every matching image is observed automatically. When the image enters the viewport area, FrontAlign loads the real image, removes data-src, adds .fa-image-loaded, and removes the shimmer layer.

Lazy Image is intentionally attribute-first. There is no special class required for the initial markup, and there is no manual initialization required in normal usage.

Required Markup

The minimal required markup is a normal image with data-src.

AttributeRequiredRole
data-srcYesStores the real image URL. FrontAlign reads this value and assigns it to src only when the image should load.
altRecommendedProvides accessible text for screen readers and fallback context when the image cannot be displayed.
width / heightRecommendedReserves layout space and helps prevent layout shift before the image is loaded.
data-error-textNoOverrides the default fallback message shown when the image fails to load.
<img
  data-src="/images/products/headphones.jpg"
  data-error-text="Product image could not be loaded"
  alt="Wireless headphones"
  width="640"
  height="420"
/>

Loading Behavior

Lazy Image uses IntersectionObserver to load images only when they are close to the viewport.

StepWhat happens
ObserveFrontAlign finds every image matching img[data-src] and starts observing it.
Near viewportWhen the image intersects the observer area, LazyImage.load() is called.
WrapThe image is wrapped in .fa-image-wrap, then shimmer and error layers are generated.
PreloadA temporary Image() instance loads the URL from data-src before the real image is updated.
SuccessThe real image receives src, data-src is removed, .fa-image-loaded is added, and shimmer is removed.
ErrorShimmer is removed, data-src is removed, and .fa-image-error-layer.is-visible is shown.

Observer settings

FrontAlign starts image loading slightly before the image becomes fully visible. This makes the image feel ready by the time the user scrolls to it.

SettingValuePurpose
rootMargin100px 0pxStarts loading around 100px before the image reaches the viewport.
threshold0.1Triggers loading when a small part of the image intersects the observer area.
selectorimg[data-src]The default selector used by LazyImage.observe().

After an image starts loading, it is unobserved so the same image is not processed again.

Dynamic Images

Lazy Image also watches the DOM with MutationObserver. Images added later are automatically observed as long as they match img[data-src].

This is useful for API-driven UIs, infinite lists, filters, tabs, modals, and components that render after the first page load.

<div id="gallery"></div>

<script>
  const gallery = document.querySelector('#gallery');

  gallery.insertAdjacentHTML('beforeend', `
    <img
      data-src="/images/gallery/new-photo.jpg"
      alt="New gallery photo"
      width="800"
      height="500"
    />
  `);
</script>

You do not need to call LazyImage.observe() again for dynamically inserted images when the FrontAlign runtime is already active.

Error Fallback

If the image cannot be loaded, Lazy Image displays a generated fallback layer.

<img
  data-src="/images/missing-image.jpg"
  data-error-text="Preview unavailable"
  alt="Preview"
  width="640"
  height="420"
/>

The error layer includes:

  • A default inline SVG image icon
  • A fallback text message
  • The .is-visible state class after failure

If data-error-text is not provided, the default message is Image failed to load.

StateClass / attributeResult
Initialdata-srcThe real image URL is waiting to be loaded.
Loading.fa-image-shimmerGenerated shimmer layer is visible.
Loaded.fa-image-loadedThe image is loaded successfully and can be animated with CSS.
Error.fa-image-error-layer.is-visibleThe fallback icon and message are displayed.

Accessibility

Lazy loading must not remove the meaning of the image. Treat every lazy image like a normal image.

Recommended practices:

  • Always provide meaningful alt text for content images.
  • Use empty alt="" only for decorative images.
  • Add width and height to reduce layout shift.
  • Do not put important text only inside an image.
  • Use data-error-text when a failed image needs clear context.
  • Keep error text short and understandable.
<img
  data-src="/images/team/founder.jpg"
  alt="Founder speaking at a product launch"
  data-error-text="Founder photo could not be loaded"
  width="720"
  height="480"
/>

For decorative images:

<img
  data-src="/images/patterns/soft-gradient.png"
  alt=""
  width="1200"
  height="600"
/>

Class Reference

Class / selectorRole
img[data-src]Default target selector. Any image with this attribute is automatically observed by FrontAlign.
.fa-image-wrapGenerated wrapper around the image. Provides the positioning context for shimmer and error layers.
.fa-image-shimmerGenerated loading layer shown while the real image is being loaded through a temporary Image() instance.
.fa-image-error-layerGenerated fallback layer containing the default SVG icon and error text.
.is-visibleAdded to .fa-image-error-layer when loading fails.
.fa-image-loadedAdded to the image after it loads successfully. Useful for fade-in or loaded-state styling.

Notes

Lazy Image is designed to be invisible in daily use. In most projects, the complete setup is:

<img data-src="/images/photo.jpg" alt="Photo description" width="800" height="500" />

and one FrontAlign runtime on the page:

const faApp = new FrontAlign();

That is enough for automatic lazy loading, dynamic image detection, shimmer state, loaded state, and error fallback.

FrontAlign