Skip to main content

imgTag filter

The imgTag filter is a Liquid helper that renders a full <img> tag from an Image input. It is the quickest way to output a resized image with email-safe width and height attributes.

What imgTag does

When you use imgTag, Better Email:

  • outputs an <img> tag
  • uses the image metadata stored on the input
  • applies resizing rules to the src
  • includes width and height styling for more predictable rendering

If the image input has built-in alt text enabled, imgTag uses the stored altText value automatically unless you override it.

Basic example

{{ my_module.my_image | imgTag }}

Tag parameters

These parameters control the generated <img> tag itself:

  • altText: override the stored alt text value
  • class: add CSS classes
  • style: append custom inline styles
  • resize: set to false to skip resizing and use the original image URL (default: true)

Resize parameters

These parameters control how the image is resized. We use Cloudflare Images transformations behind the scenes, so the parameters follow Cloudflare's semantics.

  • width: override the width from the image input options. When only width is given, the height is auto-calculated to preserve the aspect ratio.
  • height: set an explicit height
  • dpr: override the input's device pixel ratio. Use dpr: 2 for crisp images on high-DPI/Retina screens.
  • fit: control how width and height are interpreted during resizing (default: cover). See fit modes below.
  • gravity: crop anchor when cropping — auto, face, center, top, bottom, left, right. Use face to keep detected faces in frame.
  • flip: mirror the image horizontally with h, vertically with v, or both with hv. Flip is applied before rotate.
  • zoom: control how tightly Cloudflare crops around a detected face, from 0 (include the most background) to 1 (crop most closely to the face). This only works with gravity: 'face'; it is not a general-purpose zoom control.
  • background: background color, typically used with fit: 'pad'. When fit is pad and no background is set, it defaults to transparent.
  • blur: blur amount from 0 to 250
  • brightness: brightness adjustment from 0 to 100
  • contrast: contrast adjustment from 0 to 100
  • gamma: gamma adjustment from 0 to 100
  • sharpen: sharpening strength from 0 to 10
  • rotate: rotate the image by 90, 180, or 270 degrees
  • anim: set to true to preserve animation frames in animated images (GIFs)
  • quality: output quality from 1 to 100
  • format: force an output format — avif, webp, or json
  • metadata: control image metadata in the output — keep, copyright, or none
  • trim_top / trim_left / trim_right / trim_bottom: cut off pixels from the given edge before resizing

Fit modes

  • cover (default): resize the image to fill the entire area of the given width and height. If the aspect ratio differs, the image is cropped to fit.
  • scale-down: like contain, but the image is never enlarged. If the image is larger than the given width or height it is resized; otherwise its original size is kept.
  • crop: shrink and crop the image to fit within the given width and height, but never enlarge it. For smaller images this behaves like scale-down; for larger images it behaves like cover.
  • pad: resize the image to the maximum size that fits within the given width and height, then fill the remaining area with the background color (transparent by default). A good choice for logos when you know the background color.
  • contain: avoid with imgTag. The tag styles the image to the exact requested width and height, so a contained image gets stretched and appears distorted. Use scale-down, pad, or cover instead. (contain is fine with the resizeImage filter when you control the HTML yourself.)

Advanced example

{{ my_module.my_image | imgTag: width: 200, height: 150, dpr: 2, fit: 'cover', style: 'border: 1px solid red;', class: 'my-image', altText: 'My Image' }}

Possible output:

<img alt="My Image" class="my-image" src="..." height="150" style="width: 200px; height: 150px; border: 1px solid red;" />

Flip and face-aware cropping

Mirror an image horizontally while keeping the detected face in frame:

{{ profile.photo | imgTag: width: 320, height: 320, fit: 'cover', gravity: 'face', zoom: 0.5, flip: 'h' }}

Use flip: 'v' for a vertical flip or flip: 'hv' for both directions. Face zoom accepts decimal values from 0 through 1 and requires gravity: 'face'; invalid combinations are rejected.

Draw overlays

The draw parameters place one or more overlay images on top of the resized image — for example a logo watermark, a badge, or a tiled pattern. The overlay is composited into the final image itself, so it works in every email client without any CSS positioning tricks.

You can add up to four overlays by numbering the parameter prefixes: draw1_, draw2_, draw3_, and draw4_. Overlays are drawn in order, so draw2_ renders on top of draw1_. (The unnumbered draw_ prefix is also supported for a single overlay, but prefer the numbered form.)

Each overlay supports the following parameters (shown here for draw1_):

  • draw1_url: URL of the overlay image (required for the overlay to render)
  • draw1_width / draw1_height: overlay dimensions
  • draw1_fit: how the overlay is resized within its dimensions — scale-down, contain, cover, crop, pad
  • draw1_gravity: where the overlay is anchored — auto, center, top, bottom, left, right
  • draw1_top / draw1_left / draw1_bottom / draw1_right: positional offsets in pixels from the given edge
  • draw1_opacity: overlay opacity from 0 to 1
  • draw1_repeat: tile the overlay — true (both directions), "x" (horizontally), or "y" (vertically)
  • draw1_background: background color for the overlay layer
  • draw1_rotate: rotate the overlay by 90, 180, or 270 degrees

Example: centered watermark

Place a semi-transparent logo in the center of a hero image:

{{ hero.image | imgTag: width: 640, height: 320, draw1_url: "https://example.com/logo.png", draw1_width: 160, draw1_gravity: "center", draw1_opacity: 0.9 }}

Example: badge in a corner

Position a badge 20px from the top-left corner:

{{ hero.image | imgTag: width: 640, height: 320, draw1_url: "https://example.com/badge.png", draw1_width: 80, draw1_top: 20, draw1_left: 20 }}

Example: multiple overlays

Combine a watermark with a corner badge — the badge (draw2_) is drawn on top of the watermark (draw1_):

{{ hero.image | imgTag: width: 640, height: 320, draw1_url: "https://example.com/logo.png", draw1_width: 160, draw1_gravity: "center", draw1_opacity: 0.5, draw2_url: "https://example.com/badge.png", draw2_width: 80, draw2_top: 20, draw2_right: 20 }}

Example: tiled pattern

Repeat a small pattern image across the whole image:

{{ hero.image | imgTag: width: 640, height: 320, draw1_url: "https://example.com/pattern.png", draw1_width: 40, draw1_repeat: true, draw1_opacity: 0.2 }}

The draw parameters also work with the resizeImage filter if you need the URL instead of a full tag.

Built-in image alt text

When Alt Text is enabled on an image input, the value is stored on the image itself:

{{ my_module.my_image.altText }}

That means this works out of the box:

{{ my_module.my_image | imgTag }}

And this still overrides the stored value when needed:

{{ my_module.my_image | imgTag: altText: "Override alt text" }}