gatsby-source-sanity
gatsby-source-sanity copied to clipboard
Lack of control/flexibility with SanityImage params
In order to explain why I think the current SanityImage params are not flexible enough, I'm going to give an example.
Let's say I have a 400x400 div in my website that I want to fill with an image that comes from Sanity. If I was building the image url by hand, I'd use the following params: w=400&h=400&fit=min
. This always gives me a square image (perfect for my square div), shrinks large images as needed, and doesn't scale up small images (CSS can do that if needed).
Now, using a fluid query (and yes, I know that in this specific example I could use a fixed query, but I simplified for sake of brevity), all I can say is (maxwidth: 400, maxHeight: 400)
. If the image that I have in Sanity has more that 400 width and height, I get the same image as if using the params w=400&h=400&fit=min
, but if one size of the image is smaller, let's say 500x200, it results in these params w=400&h=200&fit=crop
, which gives me an image that is not square (and thus wastes bandwidth by fetching an image where half of it is never shown, and also results in a stretched image if seen on a browser that doesn't support object-fit).
What I'd like is to have more control over the final url, first by being able to set the fit
parameter (in my case, to min
), second by not having the lib changing the aspect ratio of the values I give it (if I give it a maxWidth and maxHeight of 400, the url shouldn't have a width of 400 and height of 200, independent of the size of the image being fetched).
I know there must be a million reasons for things to be the way they are that I'm not aware of, but the way they are now is also limiting, so I was hoping to start a discussion on how we could improve things.
Yes, more control would be great. For example, define the quality somewhere of the images that are been resolved. The compression is driving me mad!
I know this is a terrible thing to do but Im just slammed and didn't have time to contribute to the project accounting for tests, so essentially pulled out https://github.com/sanity-io/gatsby-source-sanity/blob/main/src/images/getGatsbyImageProps.ts
and hacked it within my project to support extra Sanity image arguments.
I was cautious about breaking anything that had to do with image sizes so only allowed my own hack to support a subset of those options in the form of:
export type SanityImageArgs = {
bg?: string,
blur?: number,
fm?: string,
invert?: boolean,
q?: number,
sat?: number,
sharpen?: number
}
And then added that argument to the two functions, getFixedGatsbyImage
and getFluidGatsbyImage
in the form of:
export function getFluidGatsbyImage(
image: ImageNode,
args: FluidArgs,
sanityArgs: SanityImageArgs,
loc: SanityLocation,
): GatsbyFluidImageProps | null {
...
const sanityParams = Object.keys(sanityArgs || {}).map(key => key + '=' + sanityArgs[key]).join('&')
const baseSrc =
isOriginalSize(maxWidth, maxHeight) ||
(maxWidth >= dimensions.width && maxHeight >= dimensions.height)
? `${url}?${sanityParams}`
: `${url}?w=${maxWidth}&h=${maxHeight}&fit=crop&${sanityParams}`
...
const srcSets = widths
.filter((currentWidth) => currentWidth <= dimensions.width)
.reduce((acc, currentWidth) => {
const currentHeight = Math.round(currentWidth / desiredAspectRatio)
const imgUrl = isOriginalSize(currentWidth, currentHeight)
? `${url}?${sanityParams}`
: `${url}?w=${currentWidth}&h=${currentHeight}&fit=crop&${sanityParams}`
const webpUrl = convertToFormat(imgUrl, 'webp')
const baseUrl = convertToFormat(imgUrl, forceConvert || props.extension)
acc.webp.push(`${webpUrl} ${currentWidth}w`)
acc.base.push(`${baseUrl} ${currentWidth}w`)
return acc
}, initial)
...
This is then used as:
const fluid = getGatsbyImageProps.getFluidGatsbyImage(
banner.asset.id,
{
maxHeight: 2400,
maxWidth: 2400
},
{
q: 30
}
sanityConfig
);
Maybe this will help inspire a nice update to this package if anything. Here is a gist.
Ok ended up making a pull request for this: https://github.com/sanity-io/gatsby-source-sanity/pull/95
For anyone else struggling with this, there's a Gatsby plugin that might help: https://www.sanity.io/plugins/gatsby-plugin-sanity-image