How-to library · Developer docs

How-to library

Task-shaped pages: a title that starts with a verb, the situation in a few lines, the steps, the working code in both engines, and why this way rather than another. Found from a search, done, and left.

Attach alt text and a crop as attributes of an image area

An attached attribute is an attribute with a parent: it sits behind a cog next to the image field and moves with it. Add imageAlt (text) and imageCrop (select) with the image as parent, and read them by name.

Context

Context. Alt text and a crop mode mean nothing without the image, so they belong with it, not in a general attributes tab. An attached attribute is an attribute whose parent is another, non-attribute area on the same layout. It appears behind a cog next to the parent's field and moves into the parent's group, directly after it. The parent must be saved before the attribute can point at it.

Steps

  1. Save the layout with the image area (Image) first.
  2. Add imageAlt, input type Text, tick Attribute, parent image.
  3. Add imageCrop, a select input type with options fit::Fill the frame, auto::Fit inside, crop::Cut a detail, default fit; tick Attribute, parent image.
  4. Read all three by name. Fall back to the image's own name when the alt text is empty.

Template code

Template code
{$image = $component->getAreaImage('image')}
{if !$image->isBlank()}
  {$alt = $component->getAreaText('imageAlt')|default:$image->getName()}
  {$crop = $component->getAreaText('imageCrop')|default:'fit'}
  {$image->getResized(1200, 675, $crop)->getHtml(['alt' => $alt|escape, 'loading' => 'lazy'])}
{/if}
{% set image = component.getAreaImage('image') %}
{% if not image.isBlank() %}
  {% set alt = component.getAreaText('imageAlt')|default(image.getName()) %}
  {% set crop = component.getAreaText('imageCrop')|default('fit') %}
  {{ image.getResized(1200, 675, crop).getHtml({'alt': alt|e, 'loading': 'lazy'}) }}
{% endif %}

Why this and not that

Not the image's file-manager name as the only alt text: it is a file name most of the time. Not a free-text crop: the option keys are exactly the strategy names getResized() accepts, so the select doubles as validation. Not layout-level attributes for these two: the rule is "would the setting still make sense if the field were empty?", and a crop of nothing does not.

Go deeper

Was this page helpful?

Your answer goes to the docs team.