diff --git a/.changeset/shaky-bananas-clap.md b/.changeset/shaky-bananas-clap.md new file mode 100644 index 000000000000..774bb8ba9331 --- /dev/null +++ b/.changeset/shaky-bananas-clap.md @@ -0,0 +1,23 @@ +--- +'astro': minor +--- + +Adds a new `background` property to the `` component. + +This optional property lets you pass a background color to flatten the image with. By default, Sharp uses a black background when flattening an image that is being converted to a format that does not support transparency (e.g. `jpeg`). Providing a value for `background` on an `` component, or passing it to the `getImage()` helper, will flatten images using that color instead. + +This is especially useful when the requested output format doesn't support an alpha channel (e.g. `jpeg`) and can't support transparent backgrounds. + +```astro +--- +import { Image } from 'astro:assets'; +--- +A JPEG with a white background! +``` + +See more about this new property in [the image reference docs](https://docs.astro.build/en/reference/modules/astro-assets/#background) diff --git a/packages/astro/src/assets/consts.ts b/packages/astro/src/assets/consts.ts index 5fae641ae462..5ca3809df906 100644 --- a/packages/astro/src/assets/consts.ts +++ b/packages/astro/src/assets/consts.ts @@ -34,4 +34,5 @@ export const DEFAULT_HASH_PROPS = [ 'quality', 'fit', 'position', + 'background', ]; diff --git a/packages/astro/src/assets/services/service.ts b/packages/astro/src/assets/services/service.ts index 0ce8fbd4c338..0c5b4b008032 100644 --- a/packages/astro/src/assets/services/service.ts +++ b/packages/astro/src/assets/services/service.ts @@ -111,7 +111,7 @@ export interface LocalImageService = Record a - b; @@ -254,6 +255,7 @@ export const baseService: Omit = { priority, fit, position, + background, ...attributes } = options; return { @@ -363,6 +365,7 @@ export const baseService: Omit = { f: 'format', fit: 'fit', position: 'position', + background: 'background', }; Object.entries(params).forEach(([param, key]) => { @@ -397,6 +400,7 @@ export const baseService: Omit = { quality: params.get('q'), fit: params.get('fit') as ImageFit, position: params.get('position') ?? undefined, + background: params.get('background') ?? undefined, }; return transform; diff --git a/packages/astro/src/assets/services/sharp.ts b/packages/astro/src/assets/services/sharp.ts index 82646ffdeeeb..d89449a9b6e1 100644 --- a/packages/astro/src/assets/services/sharp.ts +++ b/packages/astro/src/assets/services/sharp.ts @@ -100,6 +100,13 @@ const sharpService: LocalImageService = { }); } + // If background is set, flatten the image with the specified background. + // We do this after resize to ensure the background covers the entire image + // even if its size has expanded. + if (transform.background) { + result.flatten({ background: transform.background }); + } + if (transform.format) { let quality: number | string | undefined = undefined; if (transform.quality) { diff --git a/packages/astro/src/assets/types.ts b/packages/astro/src/assets/types.ts index 820988ec7e91..c96befc9e91f 100644 --- a/packages/astro/src/assets/types.ts +++ b/packages/astro/src/assets/types.ts @@ -89,6 +89,7 @@ export type ImageTransform = { format?: ImageOutputFormat | undefined; fit?: ImageFit | undefined; position?: string | undefined; + background?: string | undefined; [key: string]: any; } & Astro.CustomImageProps;