Skip to content

Twig components

The bundle provides a set of Twig components to display media in your templates using HTML best practices.

<img> tag

The img tag is the most common way to display images in HTML. The bundle provides a Twig component to generate the img tag with the correct src attribute depending on the media and the variation you want to display.

<twig:joli:Img
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
/>

This outputs an img tag with the correct src attribute and default settings:

<img
    src="/path/to/cache/variation-name/example-image.png"
    alt="Alternative text"
    width="200"
    height="200"
    loading="lazy"
    decoding="async"
/>

If the image is stored in the default library, you can omit the library attribute, the component will use the default library. If, however, the image is stored in a different library, you can specify the library name:

<twig:joli:Img
    path="example-image.png"
    variation="variation_name"
    library="library_name"
    alt="Alternative text"
/>

As you can see, the image width and height are automatically set to the media file intrinsic dimensions. The loading and decoding attributes are also set to lazy and async respectively to improve the page loading performance. This behavior can however be customized by passing additional loading and decoding attributes to the component:

<twig:joli:Img
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    loading="{{ false }}"
    decoding="{{ false }}"
/>

generates:

<img
    src="/path/to/cache/variation-name/example-image.png"
    alt="Alternative text"
    width="200"
    height="200"
/>

The skipAutoDimensions attribute can be used to prevent the component from setting the width and height attributes:

<twig:joli:Img
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    skipAutoDimensions
/>

generates:

<img
    src="/path/to/cache/variation-name/example-image.png"
    alt="Alternative text"
    loading="lazy"
    decoding="async"
/>

Alternatively, you can also manually set the width and/or height attributes. If one of these attributes is set, skipAutoDimensions is automatically considered as true:

<twig:joli:Img
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    width="100"
/>

generates:

<img
    src="/path/to/cache/variation-name/example-image.png"
    alt="Alternative text"
    width="100"
    loading="lazy"
    decoding="async"
/>

If the provided image is a high pixels density image, you may wish the twig component to generate a srcset attribute with an additional pixel density descriptor. Consider the following conditions:

  • the original image high-density-image.png has 1600x1600 pixel dimensions
  • the variation variation_name is defined to resize the image to 200x200 pixels and it is defined with a pixel_ratios option set to [1,2]

The following code:

<twig:joli:Img
    path="high-density-image.png"
    alt="Alternative text"
    variation="variation_name"
/>

generates:

<img
    src="/path/to/cache/variation-name/high-density-image.png"
    alt="Alternative text"
    width="200"
    height="200"
    loading="lazy"
    decoding="async"
/>

So does the following code:

<twig:joli:Img
    path="high-density-image.png"
    alt="Alternative text"
    variation="{{ ['variation_name'] }}"
/>

You need to explicitly ask for the additional pixel density descriptor by providing an array of variation names to the variation attribute:

<twig:joli:Img
    path="high-density-image.png"
    alt="Alternative text"
    variation="{{ ['variation_name', 'variation_name_2x'] }}"
/>

generates:

<img
    src="/path/to/cache/variation-name/high-density-image.png"
    srcset="
        /path/to/cache/variation-name/high-density-image.png 200w,
        /path/to/cache/variation-name@2x/high-density-image.png 400w
    "
    sizes="200px"
    alt="Alternative text"
    width="200"
    height="200"
    loading="lazy"
    decoding="async"

The srcset and sizes attributes can be used to provide multiple image sources for different screen sizes and resolutions. The srcset attribute is a comma-separated list of image URLs and their corresponding pixel widths, while the sizes attribute specifies the intended display size of the image in different viewport conditions. In the example above, you can see that the srcset attribute contains two entries: one for the normal density (1x, ie. a 200px image displayed in a 200px box) and one for the high density (2x, ie. a 400px image displayed in a 200px box). The sizes attribute is set to 200px, which means that the image will be displayed at 200 pixels wide on all screen sizes. Of course, you can override the sizes attribute by providing a custom value (which can include media queries):

<twig:joli:Img
    path="high-density-image.png"
    alt="Alternative text"
    variation="{{ ['variation_name', 'variation_name_2x'] }}"
    sizes="600px"
/>

generates:

<img
    src="/path/to/cache/variation-name/high-density-image.png"
    srcset="
        /path/to/cache/variation-name/high-density-image.png    200w,
        /path/to/cache/variation-name@2x/high-density-image.png 400w
    "
    sizes="600px"
    alt="Alternative text"
    width="200"
    height="200"
    loading="lazy"
    decoding="async"
/>

More complex sizes attributes can also be defined, for example:

<twig:joli:Img
    path="high-density-image.png"
    alt="Alternative text"
    variation="{{ ['variation_name', 'variation_name_2x'] }}"
    sizes="(50em <= width <= 60em) 50em, (30em <= width < 50em) 30em, (width < 30em) 20em"
/>

which generates:

<img
    src="/path/to/cache/variation-name/high-density-image.png"
    srcset="
        /path/to/cache/variation-name/high-density-image.png    200w,
        /path/to/cache/variation-name@2x/high-density-image.png 400w
    "
    sizes="(50em <= width <= 60em) 50em, (30em <= width < 50em) 30em, (width < 30em) 20em"
    alt="Alternative text"
    width="200"
    height="200"
    loading="lazy"
    decoding="async"
/>

Tip

It may happen that you wish to use high pixel density images for variations that do not actually resize the image. For example, you may have a variation that only applies a watermark to the image, or changes its format to webp but you still want to provide a high pixel density version of that variation. In this case, you can define the variation with a pixel_ratios option set to [1,2] and add a resize operation with a 50% scale to the variation processing chain.

<picture> tag

The picture tag is used to provide multiple sources for an image, allowing the browser to choose the best one depending on the device's screen size, resolution, and other factors. The bundle provides a Twig component to generate the picture tag with the correct srcset attribute depending on the media and the variations you want to display.

<twig:joli:Picture
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    picture:class="picture-class"
    img:class="image-class"
/>

generates:

<picture class="picture-class">
    <source
        srcset="/path/to/cache/variation-name-webp/example-image.b79a8399.webp"
        type="image/webp"
        width="200"
        height="200"
    >
    <img
        src="/path/to/cache/variation-name/example-image.png"
        class="image-class"
        alt="Alternative text"
        width="200"
        height="200"
        loading="lazy
        decoding="async"
    >
</picture>

Tip

Note, in the example above, that a source tag has been generated for the webp alternative format. This is done automatically if the enable_auto_webp configuration directive is set to true in the configuration file. If you want to disable this behavior, you can set the enable_auto_webp attribute to false.

The sources attribute can be a bit more fine-grained by providing the precise list of the variations you want to use, for example:

<twig:joli:Picture
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    picture:class="picture-class"
    img:class="image-class"
    sources="{{ ['first_variation_name','second_variation_name'] }}"
/>

generates the exact same HTML as the previous example, but with two additionnal source tags for the variations you specified. Note that these sources come with the right mime-type, and the width and height attributes are set to the media file intrinsic dimensions:

<picture class="picture-class">
    <source
        srcset="/path/to/cache/first-variation-name/example-image.png"
        type="image/png"
        width="400"
        height="400"
    >
    <source
        srcset="/path/to/cache/second-variation-name/example-image.png"
        type="image/png"
        width="300"
        height="300"
    >
    <source
        srcset="/path/to/cache/variation-name-webp/example-image.b79a8399.webp"
        type="image/webp"
        width="200"
        height="200"
    >
    <img
        src="/path/to/cache/variation-name/example-image.png"
        class="image-class"
        alt="Alternative text"
        width="200"
        height="200"
        loading="lazy
        decoding="async"
    >
</picture>

Going a step further, the sources attribute can be expressed as a combination of media and srcset options. This allows to define responsive images that adapt to different screen sizes and resolutions. See the following example:

<twig:joli:Picture
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    picture:class="picture-class"
    img:class="image-class"
    sources="{{ [
        {
            media: '(min-width: 1024px)',
            srcset: 'variation-extra-large',
        }, {
            media: '(max-width: 1023px)',
            srcset: 'variation-large',
        }
    ] }}"
/>

The above code generates the following HTML:

<picture class="picture-class">
    <source
        media="(min-width: 1024px)"
        srcset="/path/to/cache/variation-extra-large-webp/example-image.d601f6f2.webp"
        type="image/webp"
        width="2560"
        height="2560"
    >
    <source
        media="(min-width: 1024px)"
        srcset="/path/to/cache/variation-extra-large/example-image.png"
        type="image/png"
        width="2560"
        height="2560"
    >
    <source
        media="(max-width: 1023px)"
        srcset="/path/to/cache/variation-large-webp/example-image.d601f6f2.webp"
        type="image/webp"
        width="1920"
        height="1920"
    >
    <source
        media="(max-width: 1023px)"
        srcset="/path/to/cache/variation-large/example-image.png"
        type="image/png"
        width="1920"
        height="1920"
    >
    <source
        srcset="/path/to/cache/variation-name-webp/example-image.d601f6f2.webp"
        type="image/webp"
        width="200"
        height="200"
    >
    <img
        src="/path/to/cache/variation-name/example-image.png"
        class="image-class"
        alt="Alternative text"
        width="200"
        height="200"
        loading="lazy
        decoding="async"
    >
</picture>

The HTML <img> and picture tags expose a lot of options to customize the output: srcset, sizes, type, media, class, style, etc. The joli:Picture twig component offers ways to customize all these options to match your requirements. See the example below:

<twig:joli:Picture
    path="example-image.png"
    variation="variation_name"
    alt="Alternative text"
    picture:class="picture-class"
    img:class="image-class"
    sources="{{ [
        {
            media: '(width > 1024px)',
            sizes: '1920px',
            srcset: {
                '1920w': 'variation-large',
                '2560w': 'variation-extra-large'
            }
        },
        {
            media: '(width > 768px)',
            sizes: '1024px',
            srcset: {
                '1024w': 'variation-medium',
                '1600w': 'variation-large'
            }
        },
    ] }}"
/>

This will generate the following HTML:

<picture class="picture-class">
    <source
        media="(width > 1024px)"
        sizes="1920px"
        srcset="
            /media/cache/variation-large-webp/example-image.b79a8399.webp 1920w,
            /media/cache/variation-extra-large-webp/example-image.b79a8399.webp 2560w
        "
        type="image/webp"
        width="1920"
        height="1280"
    >
    <source
        media="(width > 1024px)"
        sizes="1920px"
        srcset="
            /media/cache/variation-large/example-image.png 1920w,
            /media/cache/variation-extra-large/example-image.png 2560w
        "
        type="image/png"
        width="1920"
        height="1280"
    >
    <source
        media="(width > 768px)"
        sizes="1024px"
        srcset="
            /media/cache/variation-small-webp/miexample-imagere.b79a8399.webp 1024w,
            /media/cache/variation-large-webp/example-image.b79a8399.webp 1600w
        "
        type="image/webp"
        width="1024"
        height="683"
    >
    <source
        media="(width > 768px)"
        sizes="1024px"
        srcset="
            /media/cache/variation-small/example-image.png 1024w,
            /media/cache/variation-large/example-image.png 1600w
        "
        type="image/png"
        width="1024"
        height="683"
    >
    <source
        srcset="/media/cache/variation-name-webp/example-image.b79a8399.webp"
        type="image/webp"
        width="200"
        height="200"
    >
    <img
        src="/path/to/cache/variation-name/example-image.png"
        class="image-class"
        alt="Alternative text"
        width="200"
        height="200"
        loading="lazy
        decoding="async"
    >
</picture>

<source> tag

Would you need even more control over the <picture> tag, you can use the joli:Source component. This component generates a <source> tag with the correct srcset attribute, depending on the media and the variations you want to display.

For example, the following code:

<twig:joli:Source
    media="{{ media }}"
    mediaAttr="(width > 1024px)"
    sizes="1024px"
    srcset="{{ {
        '1920w': 'variation-large',
        '2560w': 'variation-extra-large'
    } }}"
/>

will generate the following HTML:

<source
    media="(width > 1024px)"
    sizes="1024px"
    srcset="
        /media/cache/variation-large/example-image.png       1920w,
        /media/cache/variation-extra-large/example-image.png 2560w
    "
    type="image/png"
    width="1920"
    height="1280"
/>

If the list of the variation names provided in the srcset attribute resolve to multiple different mime types, then the component will throw an exception. This is to ensure that the <source> tag is valid and that the browser can choose the best source depending on the device's screen size, resolution, and other factors. You can fix such cases by using multiple twig:joli:Source components, one for each mime type.

If you prefer to output the complete HTML by hand and only let the bundle generate media URLs, have a look at the Twig filters provided by the bundle to generate URLs.

When are media variation files generated?

When the joli:Img or joli:Picture components are used, the media variation files are by default not generated - only their URL is. This is done to improve the performance of the page loading, as generating the media variation files can be a time-consuming process. Media variation files are usually generated and stored in the cache storage when the variation is requested for the first time (using the MediaController controller), or on demand using the joli:media:convert command.

This means that, when using the joli:Img or joli:Picture components for displaying a newly created media, that does not yet have variation files, the bundle will not be able to retrieve the mime-type, the dimensions and some other information about the requested media variation files. And, by consequence, the <img> and <picture> tags will not be able to set the width, height, type, sizes, etc. attributes.

This could be a problem if you are picky about the HTMl attributes or if you do not want media variatiosn to be generated on the fly. In this case, you can set the must_store_when_generating_url attribute to true in the cache storage configuration to have the media variation files generated when the URL is generated:

joli_media:
    libraries:
        default:
            cache:
                must_store_when_generating_url: true