image_tag - Liquid Filter Reference
On this page
Description
The image_tag filter turns an image into a complete <img> element in one call. Given an Image object, it builds a Cloudinary URL at the size you ask for, adds a responsive srcset, fills in the alt text from the media record, and sets width, height, loading and decoding so the browser can reserve space and load the image efficiently.
| Property | Value |
|---|---|
| Return Type | string (HTML) |
| Category | images |
| Available in | Storefront templates. Not available in POS templates. |
```liquid
{{ product.image | image_tag: width: 800, sizes: “(max-width: 640px) 100vw, 50vw” }} ```
The filter accepts two kinds of input:
- An Image object, such as
product.imageorarticle.hero_image. The filter reads the media record to build the URL, fill in the alt text and dimensions, and generate asrcset. - A URL string, usually the output of
image_url. Without the media record, the filter emits only the attributes you pass, plus the defaultloadinganddecodingvalues. No alt text, dimensions orsrcsetare derived.
Any other input returns an empty string.
Options
The width, height, crop and quality options work exactly as they do for image_url: the image is never enlarged past the original, no dimension exceeds 5120 pixels, and a missing dimension is calculated from the aspect ratio.
| Option | Default | Description |
|---|---|---|
width |
Original width | Width in pixels. |
height |
Calculated from the aspect ratio | Height in pixels. |
crop |
fit |
Cloudinary crop mode: fit, fill, scale, pad, crop, thumb or limit. |
quality |
auto |
auto, best, good, eco, low, none, or a number from 1 to 100. |
alt |
The image’s Alt Text | Alt text. With a URL string input, the default is empty. |
class |
None | CSS classes. |
id |
None | HTML id. |
loading |
lazy |
lazy or eager. |
decoding |
async |
async, sync or auto. |
fetchpriority |
None | high, low or auto. |
sizes |
None | The sizes attribute. Emitted only when the tag has a srcset. |
widths |
The default width ladder | Comma-separated widths to build the srcset from, such as "400,800,1200". srcset_widths is accepted as an alias. |
srcset |
Generated | An explicit srcset string, output as written. Pass srcset: nil to leave the attribute off. |
data-*, aria-* |
None | Passed through to the element, for example data-zoom: "true" or aria-label: "Front view". |
An unrecognized value for loading, decoding, crop or fetchpriority falls back to the default. Attributes other than those listed, including event handlers such as onclick, are never output, and every value is HTML-escaped.
How the srcset is built
For an Image object, image_tag generates a srcset automatically when all of these are true:
- The image is hosted on Cloudinary and is not a GIF or SVG.
- The media record has a stored width and height.
- The crop is
fitorlimit(the aspect ratio is preserved). qualityis left at the default.
The candidates come from a fixed ladder of widths: 320, 400, 512, 640, 800, 1024, 1280, 1600 and 2048 pixels. Widths larger than the original image are left out. When you pass width, the ladder stops at the first width that reaches twice that value, so a high-density screen can still pick a sharp image without the browser being offered anything larger.
To control the candidates yourself, pass widths. This also works with an exact crop such as fill, and with a custom quality, where the default ladder is skipped. Each candidate keeps the crop and aspect ratio of the src.
:::tip
Always pass sizes with a responsive image. Without it, the browser assumes the image fills the full viewport width and downloads a larger file than it needs.
:::
Width and height attributes
The width and height attributes describe the image the browser receives, not the box you asked for. With fit or limit, a box that does not match the image’s shape delivers a smaller image in one direction, and the attributes follow that delivered size. For example, a 1600 by 1200 image requested at width: 800, height: 800 is delivered at 800 by 600, and the tag carries width="800" height="600". Exact crops such as fill fill the box, so the attributes match the request.
Examples
A product card image that loads lazily and picks a size from the default ladder. The product image here is 1600 by 1200 pixels, with the alt text “Blue linen shirt”:
```liquid
{{ product.image | image_tag: width: 400, sizes: “(max-width: 640px) 50vw, 25vw”, class: “product-card__image” }} ```
Output (URLs shortened):
```html
```
A hero image above the fold, cropped to an exact box, with explicit candidate widths and a high fetch priority:
```liquid
{{ article.hero_image | image_tag: width: 1600, height: 600, crop: “fill”, widths: “800,1200,1600”, sizes: “100vw”, loading: “eager”, fetchpriority: “high”, alt: article.title }} ```
An image with data and ARIA attributes for a gallery script:
```liquid
{{ product.image | image_tag: width: 800, data-zoom: “true”, aria-label: product.name }} ```
Chaining from image_url, for themes ported from Shopify:
```liquid
{{ product.image | image_url: width: 800 | image_tag: alt: product.name, class: “hero” }} ```
This form has no srcset or dimensions unless you pass them, so prefer passing the Image object straight to image_tag.
Was this article helpful?
Thanks for your feedback! It helps us improve our docs.