Add Symfony UX Image component
| Q | A |
|---|---|
| Bug fix? | no |
| New feature? | yes |
| Deprecations? | no |
| Documentation? | yes |
| Issues | |
| License | MIT |
New symfony/ux-image component providing optimized responsive image components with automatic format conversion, smart cropping, and Core Web Vitals optimization.
Components
<twig:img> - Simple responsive images
- Automatic WebP conversion
- Responsive srcset/sizes generation
- Viewport-based width configuration (
100vw md:80vw lg:50vw) - Density-based srcset support (
densities="1x 2x") - Smart cropping with ratio and focal point
- Automatic preload injection for LCP optimization
<twig:picture> - Art direction support
- Breakpoint-specific aspect ratios (
ratio="sm:1:1 md:16:9") - Ratio cascading (like CSS) - ratios inherit to larger breakpoints
- Exclusive media queries for correct aspect ratio selection
- Different crops per viewport size
Usage Examples
{# Simple responsive image #}
<twig:img
src="/images/hero.jpg"
alt="Hero"
width="100vw sm:50vw md:400px"
ratio="16:9"
:preload="true"
/>
{# Art direction - different aspect ratios per breakpoint #}
<twig:picture
src="/images/banner.jpg"
alt="Banner"
width="100vw md:80vw"
ratio="sm:1:1 md:16:9"
/>
Thank you very much for adding this new component.
Yeah that's very nice! Please let me the week (work work work) before i'm starting a full review...
... just to anticipate, would you be OK to trim down the component to the strict bare minimum, and then we build upon it ? (not saying it's not perfect yet, not enough time to review as I said 😅 )
Anyway... thank you for this wonderful contribution.
Well, this is indeed a lot of work, thank you for this generous and ambitious PR.
After a first read and digging into the code a bit ... l'll need a bit of time to write a more detailed / in-depth review and explain what I'm thinking here, but here's a first batch of questions or comments :)
First and main one: this component does way too much for a first version. A smaller one would allow to focus on its core "essence".. right now i fear we lose much time in the many details such scope bring (e.g. breakpoint with fixed order).
I'm not sure what the primary goal of the bundle is as it stands: make <img> tags easier to use in Twig? Make image manipulation via external services easier? Handle breakpoints and responsive formats?
But it feels more "UX Image CDN" than UX Image to me. But only via a twig component, which is weird as full CDN images are mostly used by Symfony apps in full API mode.
Correct me if I'm wrong, there is currently no way for an app with "local" files, or files not generated on-demand via external services, to use <twig:image> or <twig:pictures>?
As @WebMamba noted, you had Liip bundle registered, but this is not something we should or would do here. A bundle is not supposed to require another one, and this would bring a lot of dependencies that users do not want if they use another "provider".
Side note: if we release a <twig:image />, we must also release the component without the HTML syntax ({{ component('image', ...) }}), and even without TwigComponent as a Twig function ({{ ux_image(...) }}).
(By the way, the component name will probably be twig:ux:image or twig:ux:img, as we do not want to override existing Twig components, and it would be consistent with ux:icon or ux:map.)
Regarding the implementation, I do think we would be safer using objects for the values we deal with internally and pass to the providers (Image, Filters, ...). And we should probably differentiate a bit more between the resize / filter / convert parts, to offer dedicated helpers / runtime checks / etc.
Lastly, I do not think the PreloadManager feature is something this component should offer (at least not "out of the box" / by default when someone simply wants to add preload=true on an image). It may improve performance a tiny bit in some very specific scenarios... but the vast majority of the time, for server-rendered pages, it will do the exact opposite :/
Google explicitly advises against using the preload link or header for images in various pages/articles on web.dev (see below). I'd remove this part entirely at first.
So right now I'm tempted to say there are plenty of good things in your PR, there is work to do, but if you agree to slim down the scope, we can iterate on it and see if this brings us to a good place?
About preloading images and why it's a bad idea 99% of the time in a Symfony app:
Some reading for anyone interested in this topic:
Hi!
But it feels more "UX Image CDN" than UX Image to me.
And I think it's fine, IMHO this is what people will expect when using this component. People want to easily embed images in their app and lets the tool do automatic transformations for them. If they really want to manipulate an image, its their decision to manually use Gd, Imagine, etc...
I didn't read the code yet, but this should behave like Unpic or other equivalent images embedding libraries.
You msut be able to configure CDN adapters:
- like Cloudflare Images URL that will be especially useful in your production app,
- but also a "local adapter" like https://glide.thephpleague.com/ that will be useful in local development as it won't impact $$$, but this must not be added as a hard-requirement
- maybe even better, an adapter only based on a url pattern
I do agree on that, but to me we cannot offer an ux_image function that cannot render an image for local assets (even in static way / non transormers)
nothing that cannot be done here :)