Skip to content

adds ImageTransform.background#15153

Merged
Princesseuh merged 3 commits intowithastro:mainfrom
jcayzac:jpeg-background
Jan 28, 2026
Merged

adds ImageTransform.background#15153
Princesseuh merged 3 commits intowithastro:mainfrom
jcayzac:jpeg-background

Conversation

@jcayzac
Copy link
Contributor

@jcayzac jcayzac commented Jan 9, 2026

Changes

This adds support for providing a background color in image transforms. Right now Astro has no support for that, so the background of anything converted to e.g. jpeg is always Sharp's default black.

Testing

I'd need some help figuring how to implement a test for this. Is there a way to render a JPEG to a <canvas> in a headless browser inside Astro tests?

Docs

Some documentation updates are definitely needed for this, to document the new field.

/cc @withastro/maintainers-docs for feedback!

@changeset-bot
Copy link

changeset-bot bot commented Jan 9, 2026

🦋 Changeset detected

Latest commit: f68d125

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the pkg: astro Related to the core `astro` package (scope) label Jan 9, 2026
@codspeed-hq
Copy link

codspeed-hq bot commented Jan 9, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing jcayzac:jpeg-background (f68d125) with main (94ac011)

Open in CodSpeed

@jcayzac
Copy link
Contributor Author

jcayzac commented Jan 9, 2026

I missed a few other spots that needed updating. Doing that now.

@Princesseuh Could you explain why this doesn't check other things for equality, e.g. quality ?

const matchesValidatedTransform = (transform: ImageTransform) =>
transform.width === validatedOptions.width &&
transform.height === validatedOptions.height &&
transform.format === validatedOptions.format;

Edit: Ah, I think I get it! But now I don't get why format is included. It should only be width and height. We already know that everything else matches.

@jcayzac
Copy link
Contributor Author

jcayzac commented Jan 9, 2026

Alright, everything fixed now.
I removed support for passing an object with r, g, b and alpha values, albeit supported by Sharp, as to not make the URL params more complicate than the existing. Only string is supported now, although users can still pass rgba(r b g / alpha).

Copy link
Member

@Princesseuh Princesseuh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good with me!

@florian-lefebvre florian-lefebvre added this to the 5.17.0 milestone Jan 9, 2026
Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for providing this new feature! Left a note on the kind of changeset message we'd typically like to have!

Also, for further docs, we need to add an API reference for the new option in this section: https://docs.astro.build/en/reference/modules/astro-assets/#imagetransform (I think it's fine to add it to the end of the list, after position)

And, for example, if this is something actually set on the <Image /> component itself, then it would need to be added here https://docs.astro.build/en/reference/modules/astro-assets/#image- (I think it's fine to stick it on at the end, after priority.)

You can follow the model for the existing properties in each place this is needed. Under ImageTransform you can see the descriptions are very minimal. Properties of the <Image /> component include an initial API reference block and then the content can be something like the changeset content here, but un-hyped. Just a matter-of-fact explanation of what it is/does, and an example showing it in use.

As I explain below, I'm not sure where the user sets this value, so the key point is to make sure that it's obvious to the reader how to get started and use this new feature. That's where I'll need your help!

'astro': minor
---

Add `background` in `ImageTransform`, to allow flattening images with the given background color. This is especially useful when the requested output format doesn't support an alpha channel, e.g. `jpeg`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note here that for a minor release of a new feature, we'd usually hype it up a bit more, focusing on what a user can now do (with an example usage shown) rather than implementation details. You can see a model of this in our contributing docs.

In this case, I suspect that maybe talking about the ImageTransform type here, and possibly even flattening, is more of an implementation detail? More commonly, we'd stick to wording that closer describes what someone is trying to achieve, like in the PR description itself ("providing a background color in image transforms.")

You are the subject matter expert here, and I don't really have a good idea of how this is used: added as a property on the <Image /> component which will then be used when the image is transformed? Is this passed when using something like one of the image transform functions?

So this is just very rough, and I'm only throwing words together; may not be accurate, but we'd expect a changeset for a new feature added to guide someone though what it looks like to use the new feature something like:

Adds a new `background` property to the `<Image />` component

This optional property allows you to provide a background color for image transformations. By default, images converted to another format by Sharp use a default black background. Providing a value for `background` on an `<Image />` 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.

```
show an example of this in use
```

See more about this new property in [the image reference docs](https://docs.astro.build/en/reference/modules/astro-assets/#background)

That's the general idea anyway:

  • Quick sentence to shout "New! Shiny!" and grab people's attention without a lot of visual clutter
  • describe the problem it solves or ability it unlocks and why that's cool
  • show an example that people could copy into their projects right away to try it out so that it's easy for them to get started
  • link to the docs for the new thing

You know the feature better than I do, so you'll need to describe what makes sense to show it off, but that's the pattern!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'll make the necessary changes over the weekend.

Copy link
Contributor Author

@jcayzac jcayzac Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the reference docs, those should probably mention that

background supports any syntax supported by color-string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sarah11918 I see you're hardcoding the locale in https://docs.astro.build/en/reference/modules/astro-assets/ instead of relying on the automatic resolution of the current locale using https://docs.astro.build/reference/modules/astro-assets/. Is this what's expected? I'm OK with it but I think it can lead to links in a bogus locale incorrectly leaking into translations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sarah11918 How is the new changeset?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changeset is good @jcayzac ! See my one tiny suggestion.

https://docs.astro.build/en/reference/modules/astro-assets/ instead of relying on the automatic resolution of the current locale using https://docs.astro.build/reference/modules/astro-assets/. Is this what's expected?

All docs links are written with a locale, even the English ones. That's the URL people will arrive at anyway, and always see in their browser, so no reason to create a redirect!

fix outdated comment

add missing url param handling, and remove support for object

move sharp's flatten() after any resize()
@jcayzac jcayzac force-pushed the jpeg-background branch 3 times, most recently from 12902ab to 80da645 Compare January 14, 2026 03:54
Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is looking great to me! (One small suggestion). Just a reminder that we don't merge this PR or consider the feature done until docs are added, though, so please do make a Docs PR to add background! You can follow the existing examples, and if you need it find info on how we document the API references (yes, including the line break 😅 ) in the contributing guide here: https://contribute.docs.astro.build/reference/api-references/

'astro': minor
---

Add `background` in `ImageTransform`, to allow flattening images with the given background color. This is especially useful when the requested output format doesn't support an alpha channel, e.g. `jpeg`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changeset is good @jcayzac ! See my one tiny suggestion.

https://docs.astro.build/en/reference/modules/astro-assets/ instead of relying on the automatic resolution of the current locale using https://docs.astro.build/reference/modules/astro-assets/. Is this what's expected?

All docs links are written with a locale, even the English ones. That's the URL people will arrive at anyway, and always see in their browser, so no reason to create a redirect!

@jcayzac
Copy link
Contributor Author

jcayzac commented Jan 17, 2026

This PR is looking great to me! (One small suggestion).

@sarah11918 Committed, thanks!

Just a reminder that we don't merge this PR or consider the feature done until docs are added, though, so please do make a Docs PR to add background! You can follow the existing examples, and if you need it find info on how we document the API references (yes, including the line break 😅 ) in the contributing guide here: https://contribute.docs.astro.build/reference/api-references/

@Princesseuh started a PR here. I would like to amend it, but I don't have any push access to the branch she created. Is it OK to make a PR that targets her branch, so we'll merge the combined result to v6?

@jcayzac
Copy link
Contributor Author

jcayzac commented Jan 19, 2026

@Princesseuh started a PR here.

Oops wrong PR, that one is for my other PR about SVG 😓
I'll make a PR for this one.

Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving for docs, and the docs PR is also good to go for the release!

@Princesseuh Princesseuh merged commit 928529f into withastro:main Jan 28, 2026
24 of 26 checks passed
@astrobot-houston astrobot-houston mentioned this pull request Jan 28, 2026
@jcayzac jcayzac deleted the jpeg-background branch January 30, 2026 05:32
dadezzz pushed a commit to dadezzz/ice-notes that referenced this pull request Feb 7, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`5.16.15` → `5.17.1`](https://renovatebot.com/diffs/npm/astro/5.16.15/5.17.1) | ![age](https://developer.mend.io/api/mc/badges/age/npm/astro/5.17.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/astro/5.16.15/5.17.1?slim=true) |

---

### Release Notes

<details>
<summary>withastro/astro (astro)</summary>

### [`v5.17.1`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#5171)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@5.17.1)

##### Patch Changes

- [#&#8203;15334](withastro/astro#15334) [`d715f1f`](withastro/astro@d715f1f) Thanks [@&#8203;florian-lefebvre](https://github.com/florian-lefebvre)! - **BREAKING CHANGE to the experimental Fonts API only**

  Removes the `getFontBuffer()` helper function exported from `astro:assets` when using the experimental Fonts API

  This experimental feature introduced in v15.6.13 ended up causing significant memory usage during build. This feature has been removed and will be reintroduced after further exploration and testing.

  If you were relying on this function, you can replicate the previous behavior manually:

  - On prerendered routes, read the file using `node:fs`
  - On server rendered routes, fetch files using URLs from `fontData` and `context.url`

### [`v5.17.0`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#5170)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@5.17.0)

##### Minor Changes

- [#&#8203;14932](withastro/astro#14932) [`b19d816`](withastro/astro@b19d816) Thanks [@&#8203;patrickarlt](https://github.com/patrickarlt)! - Adds support for returning a Promise from the `parser()` option of the `file()` loader

  This enables you to run asynchronous code such as fetching remote data or using async parsers when loading files with the Content Layer API.

  For example:

  ```js
  import { defineCollection } from 'astro:content';
  import { file } from 'astro/loaders';

  const blog = defineCollection({
    loader: file('src/data/blog.json', {
      parser: async (text) => {
        const data = JSON.parse(text);

        // Perform async operations like fetching additional data
        const enrichedData = await fetch(`https://api.example.com/enrich`, {
          method: 'POST',
          body: JSON.stringify(data),
        }).then((res) => res.json());

        return enrichedData;
      },
    }),
  });

  export const collections = { blog };
  ```

  See [the `parser()` reference documentation](https://docs.astro.build/en/reference/content-loader-reference/#parser) for more information.

- [#&#8203;15171](withastro/astro#15171) [`f220726`](withastro/astro@f220726) Thanks [@&#8203;mark-ignacio](https://github.com/mark-ignacio)! - Adds a new, optional `kernel` configuration option to select a resize algorithm in the Sharp image service

  By default, Sharp resizes images with the `lanczos3` kernel. This new config option allows you to set the default resizing algorithm to any resizing option supported by [Sharp](https://sharp.pixelplumbing.com/api-resize/#resize) (e.g. `linear`, `mks2021`).

  Kernel selection can produce quite noticeable differences depending on various characteristics of the source image - especially drawn art - so changing the kernel gives you more control over the appearance of images on your site:

  ```js
  export default defineConfig({
    image: {
      service: {
        entrypoint: 'astro/assets/services/sharp',
        config: {
          kernel: "mks2021"
        }
    }
  })
  ```

  This selection will apply to all images on your site, and is not yet configurable on a per-image basis. For more information, see [Sharps documentation on resizing images](https://sharp.pixelplumbing.com/api-resize/#resize).

- [#&#8203;15063](withastro/astro#15063) [`08e0fd7`](withastro/astro@08e0fd7) Thanks [@&#8203;jmortlock](https://github.com/jmortlock)! - Adds a new `partitioned` option when setting a cookie to allow creating partitioned cookies.

  [Partitioned cookies](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Privacy_sandbox/Partitioned_cookies) can only be read within the context of the top-level site on which they were set. This allows cross-site tracking to be blocked, while still enabling legitimate uses of third-party cookies.

  You can create a partitioned cookie by passing `partitioned: true` when setting a cookie. Note that partitioned cookies must also be set with `secure: true`:

  ```js
  Astro.cookies.set('my-cookie', 'value', {
    partitioned: true,
    secure: true,
  });
  ```

  For more information, see the [`AstroCookieSetOptions` API reference](https://docs.astro.build/en/reference/api-reference/#astrocookiesetoptions).

- [#&#8203;15022](withastro/astro#15022) [`f1fce0e`](withastro/astro@f1fce0e) Thanks [@&#8203;ascorbic](https://github.com/ascorbic)! - Adds a new `retainBody` option to the `glob()` loader to allow reducing the size of the data store.

  Currently, the `glob()` loader stores the raw body of each content file in the entry, in addition to the rendered HTML.

  The `retainBody` option defaults to `true`, but you can set it to `false` to prevent the raw body of content files from being stored in the data store. This significantly reduces the deployed size of the data store and helps avoid hitting size limits for sites with very large collections.

  The rendered body will still be available in the `entry.rendered.html` property for markdown files, and the `entry.filePath` property will still point to the original file.

  ```js
  import { defineCollection } from 'astro:content';
  import { glob } from 'astro/loaders';

  const blog = defineCollection({
    loader: glob({
      pattern: '**/*.md',
      base: './src/content/blog',
      retainBody: false,
    }),
  });
  ```

  When `retainBody` is `false`, `entry.body` will be `undefined` instead of containing the raw file contents.

- [#&#8203;15153](withastro/astro#15153) [`928529f`](withastro/astro@928529f) Thanks [@&#8203;jcayzac](https://github.com/jcayzac)! - Adds a new `background` property to the `<Image />` 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 `<Image />` 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';
  ---

  <Image
    src="/transparent.png"
    alt="A JPEG with a white background!"
    format="jpeg"
    background="#ffffff"
  />
  ```

  See more about this new property in [the image reference docs](https://docs.astro.build/en/reference/modules/astro-assets/#background)

- [#&#8203;15015](withastro/astro#15015) [`54f6006`](withastro/astro@54f6006) Thanks [@&#8203;tony](https://github.com/tony)! - Adds optional `placement` config option for the dev toolbar.

  You can now configure the default toolbar position (`'bottom-left'`, `'bottom-center'`, or `'bottom-right'`) via `devToolbar.placement` in your Astro config. This option is helpful for sites with UI elements (chat widgets, cookie banners) that are consistently obscured by the toolbar in the dev environment.

  You can set a project default that is consistent across environments (e.g. dev machines, browser instances, team members):

  ```js
  // astro.config.mjs
  export default defineConfig({
    devToolbar: {
      placement: 'bottom-left',
    },
  });
  ```

  User preferences from the toolbar UI (stored in `localStorage`) still take priority, so this setting can be overridden in individual situations as necessary.

### [`v5.16.16`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#51616)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@5.16.16)

##### Patch Changes

- [#&#8203;15281](withastro/astro#15281) [`a1b80c6`](withastro/astro@a1b80c6) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Ensures server island requests carry an encrypted component export identifier so they do not accidentally resolve to the wrong component.

- [#&#8203;15304](withastro/astro#15304) [`02ee3c7`](withastro/astro@02ee3c7) Thanks [@&#8203;cameronapak](https://github.com/cameronapak)! - Fix: Remove await from getActionResult example

- [#&#8203;15324](withastro/astro#15324) [`ab41c3e`](withastro/astro@ab41c3e) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixes an issue where certain unauthorized links could be rendered as clickable in the error overlay

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi45Mi4xMiIsInVwZGF0ZWRJblZlciI6IjQyLjkyLjEyIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: Renovate Bot <[email protected]>
Co-committed-by: Renovate Bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: astro Related to the core `astro` package (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants