Getting Started with Nuxt Image

Learn how to optimize images effortlessly in your Nuxt app using the NuxtImg component. Discover how to transform, cache, and resize images dynamically, improving performance with just a few lines of code.

Michael Thiessen
Nuxt 3

The Mastering Nuxt FullStack Unleashed Course is here!

Get notified when we release new tutorials, lessons, and other expert Nuxt content.

Click here to view course

One of the best performance improvements you can do in your web app is dealing with images properly.

The (almost) built-in NuxtImg component makes this really easy — transforming, compressing, caching, resizing, and more, with a few lines of code.

It will only take a few minutes to fill you in.

What NuxtImg does

The NuxtImg component is a drop-in replacement for all your img tags, just like NuxtLink replaces your a tags.

It makes it super easy to resize images dynamically, cache them on your Nuxt server, and use images from other providers like Cloudinary, Directus, Fastly or anywhere else you’re storing them.

Basic usage of NuxtImg

You can use the component just as you would a regular img tag — it supports everything that the native image tag does:

<template>
  <div class="p-2 md:-mx-8 lg:-mx-16">
    <NuxtImg
      class="rounded-xl shadow-lg w-full"
      :src="src"
      :alt="alt"
      @click.stop="() => (showLightbox = !showLightbox)"
      width="800"
    />
  </div>
</template>

Nuxt will even download the package and install it automatically for you. The first time you use it, you’ll see a prompt in your CLI asking you to install the NuxtImg package.

Using it like this, you won’t get most of the benefits of the component.

Caching images on your server

It will cache the images on your Nuxt server though.

Instead of fetching directly from the src URL, your Nuxt server will fetch the image and cache it. If you inspect the devtools when using this component, you’ll see the actual src used by the underlying img tag is transformed to something like /_ipx/w_800/<https://source.unsplash.com/blue-volkswagen-beetle-on-grass-field-7HNftpNvqho/6000x4000>.

The URL contains _ipx/ because Nuxt uses an unpackage tool called IPX to do all the image transformation. This fetched image and the transformed image are then cached.

This is fantastic, because it means you can use super high quality images in your app, but don’t have to rely on the provider being fast. Your server will cache the high-resolution image, along with any other versions of that image.

Configuring IPX

However, to get this to work, you have to do some configuration. But it’s very simple:

// nuxt.config.ts
export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: [
    '@nuxt/image',
  ],

    // Configure IPX here
  image: {
    domains: ['picsum.photos', 'www.google.com'],
    provider: 'ipx',
  },
});

You need to set the default provider to ipx in your nuxt.config.ts. Otherwise, you’ll have to set the provider prop on every usage of NuxtImg. You’ll also need to include any domains you want to have transformed and cached in the domains array.

Now, let’s move on to resizing and other things we can do with IPX!

Resizing and transforming images with IPX

As soon as we provide a width or height attribute on our NuxtImg component, our image will be resized with IPX:

<template>
  <div class="p-2 md:-mx-8 lg:-mx-16">
    <NuxtImg
      class="rounded-xl shadow-lg w-full"
      :src="src"
      :alt="alt"
      @click.stop="() => (showLightbox = !showLightbox)"
      width="800"
    />
  </div>
</template>

Beyond just resizing, IPX and most other providers have a ton of other transformations we can apply. Here’s a list of what IPX can do. It’s powered by Sharp, so it supports most of what Sharp can do.

For example, we can get a grayscale version by applying the grayscale modifier:

<template>
  <div class="p-2 md:-mx-8 lg:-mx-16">
    <NuxtImg
      class="rounded-xl shadow-lg w-full"
      :src="src"
      :alt="alt"
      @click.stop="() => (showLightbox = !showLightbox)"
      width="800"
      :modifiers="{ grayscale: true }"
    />
  </div>
</template>

Responsive images

One of the best features is how easy it is to make responsive images — each user gets a different version based on their device’s screen size.

To make this work, we need to use the sizes attribute. It’s a list of breakpoints and image sizes, using a format similar to TailwindCSS:

<NuxtImg
  :src="src"
  :alt="alt"
  width="6000"
  sizes="sm:600px md:800px lg:1600px xl:6000px"
/>

Here, we set four different sizes. The NuxtImg component will then fetch the correct size based on the size of the client’s screen.

And because it’s all powered by IPX, all these versions are cached on your Nuxt server.

We can also use the densities attribute to support different screen densities, like a Retina screen on a Macbook:

<NuxtImg
  :src="src"
  :alt="alt"
  width="6000"
  sizes="sm:600px md:800px lg:1600px xl:6000px"
  densities="x1 x2"
/>

Wrapping it up

Using the NuxtImg component into your web app unlocks powerful image optimizations with minimal effort.

From caching to resizing and responsive loading, this tool streamlines image management while improving performance. With just a few lines of configuration, you can deliver high-quality, fast-loading images tailored to each user’s device.

Michael Thiessen
Michael is a passionate full time Vue.js and Nuxt.js educator. His weekly newsletter is sent to over 11,000 Vue developers, and he has written over a hundred articles for his blog and VueSchool.

Follow MasteringNuxt on