---
title: "Image Optimization"
description: "Learn how to optimize images in your Nuxt application with Nuxt Image."
canonical_url: "https://nuxt.com/docs/4.x/getting-started/images"
---
# Image Optimization

> Learn how to optimize images in your Nuxt application with Nuxt Image.

Nuxt has a core module ([`@nuxt/image`](https://nuxt.com/modules/image)) to resize, transform and serve optimized images in your application:

- **Drop-in replacement:** Use [`<NuxtImg>`](https://nuxt.com/docs/4.x/api/components/nuxt-img) and [`<NuxtPicture>`](https://nuxt.com/docs/4.x/api/components/nuxt-picture) where you would write `<img>` and `<picture>`.
- **Built-in resizer:** Optimize local and remote images with [IPX](https://nuxt.com/modules/image/providers/ipx), the default provider, with no configuration.
- **40+ providers supported:** Use the image service of your CDN or CMS instead, or [write your own provider](https://nuxt.com/modules/image/advanced/custom-provider), with no vendor lock-in.
- **Responsive ready:** Serve resized images for each screen size and device pixel density.
- **Modern formats:** Convert images to WebP or AVIF for the browsers that support them.
- **Faster page loads:** Load images only when they enter the viewport with native lazy loading, and show placeholders while they load.
- **Visual stability:** Reserve space for images with `width` and `height` to prevent [layout shift](https://web.dev/articles/cls).

## Installation

Add the Nuxt Image module to your project:

```bash [Terminal]
npx nuxt add image
```

This command installs `@nuxt/image` and adds it to the `modules` of your `nuxt.config`.

::note
When you use `<NuxtImg>` or `<NuxtPicture>` in development without the module, Nuxt detects it and asks to install `@nuxt/image` for you.
::

## Usage

Use `<NuxtImg>` instead of `<img>`, and `<NuxtPicture>` instead of `<picture>`. You don't need to import them:

::code-group
```vue [NuxtImg]
<template>
  <NuxtImg
    src="/nuxt.png"
    alt="Nuxt logo"
    width="300"
    height="80"
  />
</template>
```

```vue [NuxtPicture]
<template>
  <NuxtPicture
    src="/nuxt.png"
    alt="Nuxt logo"
    width="300"
    height="80"
    format="avif,webp"
  />
</template>
```
::

The `src` property can be a [local](#local-images) or [remote](#remote-images) image.

## Local Images

Store your images in the [`public/`](https://nuxt.com/docs/4.x/directory-structure/public) directory and reference them from the root URL (`/`). For example, `public/profile.png` is available as `/profile.png`:

```vue [app/pages/index.vue]
<template>
  <NuxtImg
    src="/profile.png"
    alt="Picture of the author"
    width="500"
    height="500"
  />
</template>
```

Nuxt Image resizes the image to the given `width` and `height`. The browser also uses these values to reserve space for the image before it loads, which prevents layout shift. Nuxt Image doesn't read the intrinsic dimensions of your files, so always set `width` and `height` for images that aren't sized by CSS.

By default, Nuxt Image uses [IPX](https://nuxt.com/modules/image/providers/ipx), a self-hosted optimizer that runs on your Nuxt server. When you prerender your site with `nuxt generate`, Nuxt Image optimizes the images at build time instead.

Prerendering only generates the image sizes that are in the server-rendered HTML. An image that only renders in the browser, such as in a modal or a client-only component, has no generated file, so its URL returns a 404 error. List these images in `nitro.prerender.routes`, or use an [image provider](#image-providers). See [static images](https://nuxt.com/modules/image/advanced/static-images) for more details.

::warning
IPX doesn't run in worker runtimes. When you deploy to one, such as Cloudflare Workers, Nuxt Image serves your original images without optimization. Configure an [image provider](#image-providers), such as `cloudflare`, to optimize them.
::

::note
Nuxt Image doesn't process images in the [`app/assets/`](https://nuxt.com/docs/4.x/directory-structure/app/assets) directory, because your build tool manages them. To keep source images out of `public/`, set the [`image.dir`](https://nuxt.com/modules/image/configuration#dir) option.
::

## Responsive Images

Use the `sizes` prop to generate several image widths and let the browser pick the right one for the screen. Each value applies from a screen size and up. The screen sizes match the [Tailwind CSS breakpoints](https://nuxt.com/modules/image/configuration#screens) by default:

```vue [app/pages/index.vue]
<template>
  <NuxtImg
    src="/hero.jpg"
    alt="Mountains at sunrise"
    width="1600"
    height="900"
    sizes="100vw md:50vw xl:800px"
  />
</template>
```

In this example, the image fills the screen width on small screens, half of it from the `md` breakpoint, and is 800 pixels wide from the `xl` breakpoint. Nuxt Image generates a `srcset` with one image for each size, at both 1x and 2x pixel density. The `sizes` prop doesn't set the displayed width of the image, so use CSS to give the image these widths.

Images without `sizes`, such as icons or avatars, get a 1x and a 2x version by default, so they stay sharp on high-density screens. To change the pixel densities, use the [`densities` prop](https://nuxt.com/modules/image/usage/nuxt-img#densities) for a single image, or the [`image.densities`](https://nuxt.com/modules/image/configuration#densities) option for every image.

## Image Formats

Use the `format` prop to convert an image to a modern format:

```vue
<template>
  <NuxtImg
    src="/hero.jpg"
    alt="Mountains at sunrise"
    format="webp"
  />
</template>
```

To serve the best format that each browser supports, use `<NuxtPicture>`. It renders a `<picture>` element with one source for each format, and a fallback in a legacy format such as JPEG or PNG:

```vue
<template>
  <NuxtPicture
    src="/hero.jpg"
    alt="Mountains at sunrise"
    format="avif,webp"
  />
</template>
```

## Loading Priority

Images below the fold can wait until the user scrolls to them. Set `loading="lazy"` to load an image only when it enters the viewport:

```vue
<template>
  <NuxtImg
    src="/gallery/sunset.jpg"
    alt="Sunset over the sea"
    width="400"
    height="300"
    loading="lazy"
  />
</template>
```

The image that is the [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) of your page, such as a hero image, must load as early as possible. Use the `preload` prop to add a `<link rel="preload">` tag to the page head with a high fetch priority:

```vue
<template>
  <NuxtImg
    src="/hero.jpg"
    alt="Mountains at sunrise"
    width="1600"
    height="900"
    :preload="{ fetchPriority: 'high' }"
  />
</template>
```

## Placeholders

To show a blurred, low-quality version of the image while the full image loads, add the `placeholder` prop:

```vue
<template>
  <NuxtImg
    src="/hero.jpg"
    alt="Mountains at sunrise"
    width="1600"
    height="900"
    placeholder
  />
</template>
```

`<NuxtImg>` replaces the placeholder with the full image in the browser, so placeholders require JavaScript. Without it, the page keeps showing the placeholder.

You can also pass your own placeholder image, or set its size, quality, and blur. See the [`placeholder` prop](https://nuxt.com/modules/image/usage/nuxt-img#placeholder) for all options.

## Remote Images

To use a remote image, provide its URL in the `src` property:

```vue [app/pages/index.vue]
<template>
  <NuxtImg
    src="https://images.unsplash.com/photo-1501785888041-af3ef285b470"
    alt="Lake surrounded by mountains"
    width="500"
    height="500"
  />
</template>
```

To prevent other websites from using your server to optimize any image on the internet, Nuxt Image only optimizes remote images from domains that you allow. Add them to the `image.domains` option in your `nuxt.config`:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@nuxt/image'],
  image: {
    domains: ['images.unsplash.com'],
  },
})
```

With the default IPX provider, Nuxt Image renders images from other domains with their original URL, without optimization. Other [providers](#image-providers) can handle these images differently.

## Image Providers

If you already host your images on an image CDN or a headless CMS, Nuxt Image can use its transformation service instead of IPX. Nuxt Image supports [more than 40 providers](https://nuxt.com/modules/image/providers), such as Cloudinary, Imgix, Sanity, and Storyblok. When you deploy to Vercel, Netlify, or AWS Amplify, Nuxt Image detects and uses the platform's image service.

To use a provider, set it as the default `provider` and configure it in your `nuxt.config`:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@nuxt/image'],
  image: {
    provider: 'cloudinary',
    cloudinary: {
      baseURL: 'https://res.cloudinary.com/<your-cloud-name>/image/upload',
    },
  },
})
```

The `src` of your images is then a path on the provider:

```vue
<template>
  <NuxtImg
    src="/blog/cover.jpg"
    alt="Blog post cover"
    width="800"
    height="450"
  />
</template>
```

You can also use a provider for a single image with the [`provider`](https://nuxt.com/modules/image/usage/nuxt-img#provider) prop.

## Next Steps

See the Nuxt Image documentation for all its features:

- [`<NuxtImg>`](https://nuxt.com/modules/image/usage/nuxt-img): all props of the image component.
- [`<NuxtPicture>`](https://nuxt.com/modules/image/usage/nuxt-picture): serve several image formats.
- [`useImage()`](https://nuxt.com/modules/image/usage/use-image): generate optimized image URLs in your code, for example for CSS backgrounds.
- [Configuration](https://nuxt.com/modules/image/configuration): set defaults such as quality, formats, screen sizes, and presets.


## Sitemap

See the full [sitemap](https://nuxt.com/sitemap.md) for all pages.
