Source
myles-tan.jpg
<twig:Image> — Next.js-style image component
Prototype: symfony/ux-twig-component wired standalone (no Symfony framework) on top of Chainsaw. Inspect the generated markup — lazy loading, srcset, dimensions, blur placeholder, crop anchors and art-directed <picture> sources all come from props.
Basic — width/height, lazy by default
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="400" height="300" />
Priority — above the fold, eager + fetchpriority=high
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="400" height="300" priority />
Responsive — widths srcset + sizes
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="480" height="320"
:widths="[320, 640, 960]" sizes="(min-width: 768px) 50vw, 100vw" />
Sizes shorthand — Tailwind-style breakpoint prefixes (md:, xl:)
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="480" height="320"
:widths="[320, 640, 960]" sizes="100vw md:50vw xl:33vw" />
Layout: fixed — density srcset (1x/2x), explicit dimensions, no sizes
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="400" height="300" layout="fixed" />
Layout: constrained — width srcset capped at the intrinsic width, sizes defaults to 100vw
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="800" height="500" layout="constrained" />
Layout: full-width — width srcset, no max-width cap, sizes defaults to 100vw
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="1600" height="500" layout="full-width" />
Blur placeholder — inline ThumbHash background
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="400" height="300" placeholder="blur" />
Picture — AVIF/WebP negotiation
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="400" height="300"
:formats="['avif', 'webp']" />
Transform + provider — manipulation grammar, named factory
<twig:Image src="myles-tan.jpg" alt="Myles tan, greyscale" width="400" height="300"
:transform="{ greyscale: true }" provider="imagine-gd" class="rounded-xl" />
Anchor — compass-positioned cover crop
<twig:Image src="myles-tan.jpg" alt="Myles tan, cropped towards the top" width="400" height="180"
anchor="top" />
Focal anchor — keep the subject at 30% / 40%
<twig:Image src="myles-tan.jpg" alt="Myles tan, focal crop" width="400" height="180"
anchor="focal:0.3,0.4" />
Art direction — square on small viewports, wide above
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="480" height="200"
:sources="[
{ media: '(max-width: 640px)', width: 400, height: 400 },
]" />
Per-source manipulations — each entry is self-contained
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="480" height="200"
:sources="[
{ media: '(max-width: 640px)', width: 400, height: 400,
anchor: 'focal:0.3,0.4', transform: { greyscale: true } },
]" />
Art direction × formats — media × type fan-out
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="480" height="200"
:sources="[
{ media: '(max-width: 640px)', width: 400, height: 400 },
]"
:formats="['avif', 'webp']" />
Responsive art direction — per-source widths + sizes
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="960" height="400"
:widths="[480, 960]" sizes="(min-width: 641px) 50vw, 100vw"
:sources="[
{ media: '(max-width: 640px)', width: 640, height: 640,
widths: [320, 640], sizes: '100vw' },
]" />
Responsive art direction × formats — full fan-out, safe for cached pages (no Accept-negotiated HTML)
<twig:Image src="myles-tan.jpg" alt="Myles tan" width="960" height="400"
:widths="[480, 960]" sizes="(min-width: 641px) 50vw, 100vw"
:sources="[
{ media: '(max-width: 640px)', width: 640, height: 640,
widths: [320, 640], sizes: '100vw' },
]"
:formats="['avif', 'webp']" />