Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Bundles
  4. Symfony UX LazyImage
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • Installation
  • Usage
    • Extend the default behavior
  • Backward Compatibility promise

Symfony UX LazyImage

Edit this page

Symfony UX LazyImage

Symfony UX LazyImage is a Symfony bundle providing utilities to improve image loading performance. It is part of the Symfony UX initiative.

It provides two key features:

  • a Stimulus controller to load lazily heavy images, with a placeholder
  • a BlurHash implementation to create data-uri thumbnails for images

Installation

Before you start, make sure you have StimulusBundle configured in your app.

Then install this bundle using Composer and Symfony Flex:

1
$ composer require symfony/ux-lazy-image

If you're using WebpackEncore, install your assets and restart Encore (not needed if you're using AssetMapper):

1
2
3
4
5
6
$ npm install --force
$ npm run watch

# or use yarn
$ yarn install --force
$ yarn watch

Usage

The default usage of Symfony UX LazyImage is to use its Stimulus controller to first load a small placeholder image that will then be replaced by the high-definition version once the page has been rendered:

1
2
3
4
5
6
7
8
9
10
<img
    src="{{ asset('image/small.png') }}"
    {{ stimulus_controller('symfony/ux-lazy-image/lazy-image', {
        src: asset('image/large.png')
    }) }}

    {# Optional but avoids having a page jump when the image is loaded #}
    width="200"
    height="150"
>

With this setup, the user will initially see images/small.png. Then, once the page has loaded and the user’s browser has downloaded the larger image, the src attribute will change to image/large.png.

There is also support for the srcset attribute by passing an srcset value to the controller:

1
2
3
4
5
6
7
8
9
10
11
12
<img
    src="{{ asset('image/small.png') }}"
    srcset="{{ asset('image/small.png') }} 1x, {{ asset('image/small2x.png') }} 2x"

    {{ stimulus_controller('symfony/ux-lazy-image/lazy-image', {
        src: asset('image/large.png'),
        srcset: {
            '1x': asset('image/large.png'),
            '2x': asset('image/large2x.png')
        }
    }) }}
/>

Note

The stimulus_controller() function comes from StimulusBundle.

Instead of using a generated thumbnail that would exist on your filesystem, you can use the BlurHash algorithm to create a light, blurred, data-uri thumbnail of the image:

1
2
3
4
5
6
7
8
9
10
<img
    src="{{ data_uri_thumbnail('public/image/large.png', 100, 75) }}"
    {{ stimulus_controller('symfony/ux-lazy-image/lazy-image', {
        src: asset('image/large.png')
    }) }}

    {# Using BlurHash, the size is required #}
    width="200"
    height="150"
/>

The data_uri_thumbnail function receives 3 arguments:

  • the server path to the image to generate the data-uri thumbnail for ;
  • the width of the BlurHash to generate
  • the height of the BlurHash to generate

You should try to generate small BlurHash images as generating the image can be CPU-intensive. Instead, you can rely on the browser scaling abilities by generating a small image and using the width and height HTML attributes to scale up the image.

Extend the default behavior

Symfony UX LazyImage allows you to extend its default behavior using a custom Stimulus controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// mylazyimage_controller.js

import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
    connect() {
        this.element.addEventListener('lazy-image:connect', this._onConnect);
        this.element.addEventListener('lazy-image:ready', this._onReady);
    }

    disconnect() {
        // You should always remove listeners when the controller is disconnected to avoid side-effects
        this.element.removeEventListener('lazy-image:connect', this._onConnect);
        this.element.removeEventListener('lazy-image:ready', this._onReady);
    }

    _onConnect(event) {
        // The lazy-image behavior just started
    }

    _onReady(event) {
        // The HD version has just been loaded
    }
}

Then in your template, add your controller to the HTML attribute:

1
2
3
4
5
6
7
8
9
10
<img
    src="{{ data_uri_thumbnail('public/image/large.png', 100, 75) }}"
    {{ stimulus_controller('mylazyimage')|stimulus_controller('symfony/ux-lazy-image/lazy-image', {
        src: asset('image/large.png')
    }) }}

    {# Using BlurHash, the size is required #}
    width="200"
    height="150"
/>

Note: be careful to add your controller before the LazyImage controller so that it is executed before and can listen on the lazy-image:connect event properly.

Backward Compatibility promise

This bundle aims at following the same Backward Compatibility promise as the Symfony framework: https://symfony.com/doc/current/contributing/code/bc.html

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:

    Symfony UX is backed by

    Code consumes server resources. Blackfire tells you how

    Code consumes server resources. Blackfire tells you how

    Peruse our complete Symfony & PHP solutions catalog for your web development needs.

    Peruse our complete Symfony & PHP solutions catalog for your web development needs.

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of goabonga, a Symfony contributor

    Thanks goabonga for being a Symfony contributor

    1 commit • 4 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony

    Search by Meilisearch