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.
Reserve layout space with the aspect ratio to avoid layout shift
Published
A resized image rendered with getHtml() gets width and height attributes automatically, which is all a browser needs. For unresized images and for wrappers, use getWidth(), getHeight() and an aspect-ratio style.
Context
Context. A page jumps when an image arrives if the browser did not know its size. It knows when the <img> carries width and height, or when the element or its wrapper has an aspect-ratio. getHtml() on a resized image adds width and height from the size you asked for; on an image that was not resized it adds neither, and a lazy-loaded slider or a CSS background gets no attributes at all.
Steps
Resize every image you render, even to its own size class; the attributes come free.
Where an image is not resized, pass width and height yourself from the object.
Where the image is a background or loads later, put the ratio on the wrapper from the object's dimensions.
Style images fluidly (max-width: 100%; height: auto) so the attributes set the ratio, not the rendered size.
Template code
Template code
{* resized: width and height are emitted for you *}
{$image->getResized(800, 450, 'fit')->getHtml(['alt' => $image->getName()|escape, 'loading' => 'lazy'])}
{* not resized: pass them *}
{$image->getHtml(['width' => $image->getWidth(), 'height' => $image->getHeight(), 'alt' => $image->getName()|escape])}
{* a wrapper that reserves the space before anything loads *}
<div class="media" style="aspect-ratio: {$image->getWidth()} / {$image->getHeight()}">
{$image->getResized(1200, null)->getHtml(['alt' => $image->getName()|escape, 'loading' => 'lazy'])}
</div>
Not a fixed height in CSS: it crops or letterboxes whatever the author uploads. Not a pixel width in a style attribute passed to getHtml(): the platform takes pixel widths and heights out of the style, resizes to them and emits them as attributes, which is helpful and surprising in equal measure. Asking for only a width gives a width attribute plus an aspect-ratio style, which is enough.