Art direction sourcesets for Image component

We can get 2 different sourcesets via Graphql. However there is no way to send both to a single image component. This would be ideal for hero images with feature priority set so that desktop and mobile can have different aspect ratios using the same image.

A thread was here - [feature request] ability to do art direction images · Issue #64 · datocms/react-datocms · GitHub

exampleImage {
  mobileImage: responsiveImage(imgixParams: {auto: compress, q: 30, fit: crop, w: 390, h: 320, crop: entropy }) {
    ...responsiveImageFragment
  }
  desktopImage: responsiveImage(imgixParams: {auto: compress, q: 40, fit: crop, w: 1920, h: 640, crop: entropy }) {
    ...responsiveImageFragment
  }
}

and instead of adding 2 images to the page and hiding with css, you could

<Image
    sources = {[
        {
            data: exampleImage.mobileImage,
            media: "(max-width: 420px)",
        },
        {
            data: exampleImage.desktopImage,
        }
    ]}
/>

I agree this would be really helpful!

Hey @alessandro,

Welcome to the forum! And also tagging the OP, @kele.nakamura (sorry this is so late, first time I’m seeing this post).

It seems to me that this use case (of wanting to show a different image to mobile vs desktop) is more commonly done at the component level, isn’t it? For example, instead of (pseudocode):

<Image sources=[img1, img2] />

It’s often done (in Tailwind or Bootstrap or similar) by just hiding/showing the component altogether:

<Image sources=[desktopImg] className="hidden lg:block" />
<Image sources=[mobileImg] className="block lg:hidden" />

Is there any advantage to doing it with different aspect ratios inside the srcset itself? Doesn’t that cause issues with cumulative layout shift…? (I admit I never tried!)

If you really want to do that, I suppose you can just pull the image URL and compose your own srcSet and sizes from the sizes you want (they’re just URL parameters as a string). You can ignore the GraphQL part and just do it in the frontend directly, or if you want to keep the GraphQL part, programatically combine the mobileImage and desktopImage objects into a single one for the Image component to consume.

But it seems to me like this would be a pretty roundabout way to reinvent responsive functionality that’s been in Tailwind and Bootstrap, etc. for a long time already. It seems like using the srcset to change aspect ratios would be confusing to other developers, if nothing else, since it’s not a common practice AFAIK. Is there an advantage to doing it this way that I didn’t know about?

i think the main thing would be for hero image and fetch priority and link preload in the head, if you had 2 images both with fetch priority and preloading in the head of your document the end user actually will download both images. or just really taking advantage of what the picture tag was meant for.

but yes most approaches seem to suggest just do the 2 images, and show/hide them.

i think some of the considerations are listed in this thread - [next/image] Responsive images with "art direction" · vercel/next.js · Discussion #19880 · GitHub

I see, thanks so much for explaining! That’s an interesting nuance for sure.

Let’s leave this feature request up and see if it gets enough traction.

In the meantime, maybe separating the preload from the image component using a link tag with media queries could do the trick, as suggested by a comment in that thread? [next/image] Responsive images with "art direction" · vercel/next.js · Discussion #19880 · GitHub (if you need to preload).

If alessandro’s use case doesn’t need preloading, probably the standard CSS approach is simpler.

But thank you again for the additional details!

Hi @roger thanks for the fast feedback.
My use case is the same, you can see it live here: Strade Bianche Alpine images in the hero of the page. The image is 100vh so the cumulative layout shift shouldn’t be an isuue
I will look in the “link” solution, thanks!

1 Like

yeah this is definitely just a nice to have feature since its a specific use case really.

and there are alternative solutions as well.

1 Like