<Image>

Ejemplos

Es bueno saberlo: Si estás usando una versión de Next.js anterior a la 13, deberás consultar la documentación de next/legacy/image ya que el componente fue renombrado.

Esta referencia de API te ayudará a entender cómo usar las props y opciones de configuración disponibles para el Componente de Imagen. Para características y uso, consulta la página del Componente de Imagen.

app/page.js
import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="/profile.png"
      width={500}
      height={500}
      alt="Foto del autor"
    />
  )
}

Props

Aquí hay un resumen de las props disponibles para el Componente de Imagen:

PropEjemploTipoEstado
srcsrc="/profile.png"StringRequerido
widthwidth={500}Integer (px)Requerido
heightheight={500}Integer (px)Requerido
altalt="Foto del autor"StringRequerido
loaderloader={imageLoader}Función-
fillfill={true}Booleano-
sizessizes="(max-width: 768px) 100vw, 33vw"String-
qualityquality={80}Integer (1-100)-
prioritypriority={true}Booleano-
placeholderplaceholder="blur"String-
stylestyle={{objectFit: "contain"}}Objeto-
onLoadingCompleteonLoadingComplete={img => done())}FunciónObsoleto
onLoadonLoad={event => done())}Función-
onErroronError(event => fail()}Función-
loadingloading="lazy"String-
blurDataURLblurDataURL="data:image/jpeg..."String-
overrideSrcoverrideSrc="/seo.png"String-

Props Requeridas

El Componente de Imagen requiere las siguientes propiedades: src, width, height y alt.

app/page.js
import Image from 'next/image'

export default function Page() {
  return (
    <div>
      <Image
        src="/profile.png"
        width={500}
        height={500}
        alt="Foto del autor"
      />
    </div>
  )
}

src

Debe ser uno de los siguientes:

  • Un archivo de imagen importado estáticamente
  • Una cadena de ruta. Puede ser una URL externa absoluta o una ruta interna dependiendo de la prop loader.

Cuando se usa una URL externa, debes agregarla a remotePatterns en next.config.js.

width

La propiedad width representa el ancho renderizado en píxeles, por lo que afectará el tamaño aparente de la imagen.

Requerido, excepto para imágenes importadas estáticamente o imágenes con la propiedad fill.

height

La propiedad height representa la altura renderizada en píxeles, por lo que afectará el tamaño aparente de la imagen.

Requerido, excepto para imágenes importadas estáticamente o imágenes con la propiedad fill.

alt

La propiedad alt se utiliza para describir la imagen para lectores de pantalla y motores de búsqueda. También es el texto de respaldo si las imágenes han sido deshabilitadas o ocurre un error al cargar la imagen.

Debe contener texto que pueda reemplazar la imagen sin cambiar el significado de la página. No está destinado a complementar la imagen y no debe repetir información que ya se proporcione en los subtítulos arriba o debajo de la imagen.

Si la imagen es puramente decorativa o no está destinada al usuario, la propiedad alt debe ser una cadena vacía (alt="").

Aprende más

Props Opcionales

El componente <Image /> acepta una serie de propiedades adicionales más allá de las requeridas. Esta sección describe las propiedades más comúnmente utilizadas del componente de Imagen. Encuentra detalles sobre propiedades menos utilizadas en la sección Props Avanzadas.

loader

Una función personalizada utilizada para resolver URLs de imágenes.

Un loader es una función que devuelve una cadena de URL para la imagen, dados los siguientes parámetros:

Aquí hay un ejemplo de uso de un loader personalizado:

import Image from 'next/image'

const imageLoader = ({ src, width, quality }) => {
  return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}

export default function Page() {
  return (
    <Image
      loader={imageLoader}
      src="me.png"
      alt="Foto del autor"
      width={500}
      height={500}
    />
  )
}

Alternativamente, puedes usar la configuración loaderFile en next.config.js para configurar cada instancia de next/image en tu aplicación, sin pasar una prop.

fill

fill={true} // {true} | {false}

Un booleano que hace que la imagen llene el elemento padre, lo cual es útil cuando el width y height son desconocidos.

El elemento padre debe asignar position: "relative", position: "fixed" o position: "absolute" en el estilo.

Por defecto, al elemento img se le asignará automáticamente el estilo position: "absolute".

Si no se aplican estilos a la imagen, la imagen se estirará para ajustarse al contenedor. Puedes preferir establecer object-fit: "contain" para una imagen que se ajuste al contenedor y preserve la relación de aspecto.

Alternativamente, object-fit: "cover" hará que la imagen llene todo el contenedor y se recorte para preservar la relación de aspecto. Para que esto se vea correcto, el estilo overflow: "hidden" debe asignarse al elemento padre.

Para más información, consulta también:

sizes

Una cadena, similar a una consulta de medios, que proporciona información sobre qué tan ancha será la imagen en diferentes puntos de interrupción. El valor de sizes afectará significativamente el rendimiento de las imágenes que usan fill o que están estilizadas para tener un tamaño responsivo.

La propiedad sizes sirve para dos propósitos importantes relacionados con el rendimiento de la imagen:

  • Primero, el valor de sizes es utilizado por el navegador para determinar qué tamaño de imagen descargar, del srcset generado automáticamente por next/image. Cuando el navegador elige, aún no conoce el tamaño de la imagen en la página, por lo que selecciona una imagen que sea del mismo tamaño o más grande que el viewport. La propiedad sizes te permite indicarle al navegador que la imagen será en realidad más pequeña que el ancho completo de la pantalla. Si no especificas un valor sizes en una imagen con la propiedad fill, se usará un valor predeterminado de 100vw (ancho completo de la pantalla).
  • Segundo, la propiedad sizes cambia el comportamiento del valor srcset generado automáticamente. Si no hay un valor sizes, se genera un srcset pequeño, adecuado para una imagen de tamaño fijo (1x/2x/etc). Si se define sizes, se genera un srcset grande, adecuado para una imagen responsiva (640w/750w/etc). Si la propiedad sizes incluye tamaños como 50vw, que representan un porcentaje del ancho del viewport, entonces el srcset se recorta para no incluir valores que sean demasiado pequeños para ser necesarios.

Por ejemplo, si sabes que tu estilo hará que una imagen tenga el ancho completo en dispositivos móviles, un diseño de 2 columnas en tablets y un diseño de 3 columnas en escritorios, debes incluir una propiedad sizes como la siguiente:

import Image from 'next/image'

export default function Page() {
  return (
    <div className="grid-element">
      <Image
        fill
        src="/example.png"
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
      />
    </div>
  )
}

Este ejemplo de sizes podría tener un efecto dramático en las métricas de rendimiento. Sin el sizes de 33vw, la imagen seleccionada del servidor sería 3 veces más ancha de lo necesario. Debido a que el tamaño del archivo es proporcional al cuadrado del ancho, sin sizes el usuario descargaría una imagen que es 9 veces más grande de lo necesario.

Aprende más sobre srcset y sizes:

quality

quality={75} // {número 1-100}

La calidad de la imagen optimizada, un entero entre 1 y 100, donde 100 es la mejor calidad y por lo tanto el mayor tamaño de archivo. Por defecto es 75.

Si la configuración qualities está definida en next.config.js, la prop quality debe coincidir con uno de los valores definidos en la configuración.

Es bueno saberlo: Si la imagen fuente original ya era de baja calidad, establecer la prop quality demasiado alta podría hacer que la imagen optimizada resultante sea más grande que la imagen fuente original.

priority

priority={false} // {false} | {true}

Cuando es verdadero, la imagen se considerará de alta prioridad y se precargará. La carga diferida se desactiva automáticamente para las imágenes que usan priority.

Debes usar la propiedad priority en cualquier imagen detectada como el elemento Largest Contentful Paint (LCP). Puede ser apropiado tener múltiples imágenes con prioridad, ya que diferentes imágenes pueden ser el elemento LCP para diferentes tamaños de viewport.

Solo debe usarse cuando la imagen es visible sin hacer scroll. Por defecto es false.

placeholder

placeholder = 'empty' // "empty" | "blur" | "data:image/..."

Un marcador de posición para usar mientras la imagen se carga. Los valores posibles son blur, empty o data:image/.... Por defecto es empty.

Cuando es blur, se usará la propiedad blurDataURL como marcador de posición. Si src es un objeto de una importación estática y la imagen importada es .jpg, .png, .webp o .avif, entonces blurDataURL se llenará automáticamente, excepto cuando la imagen se detecte como animada.

Para imágenes dinámicas, debes proporcionar la propiedad blurDataURL. Soluciones como Plaiceholder pueden ayudar con la generación de base64.

Cuando es data:image/..., la URL de datos se usará como marcador de posición mientras la imagen se carga.

Cuando es empty, no habrá marcador de posición mientras la imagen se carga, solo espacio vacío.

Pruébalo:

Props Avanzadas

En algunos casos, es posible que necesites un uso más avanzado. El componente <Image /> acepta opcionalmente las siguientes propiedades avanzadas.

style

Permite pasar estilos CSS al elemento de imagen subyacente.

components/ProfileImage.js
const imageStyle = {
  borderRadius: '50%',
  border: '1px solid #fff',
}

export default function ProfileImage() {
  return <Image src="..." style={imageStyle} />
}

Recuerda que las props requeridas de ancho y altura pueden interactuar con tu estilo. Si usas estilos para modificar el ancho de una imagen, también debes establecer su altura en auto para preservar su relación de aspecto intrínseca, o tu imagen se distorsionará.

onLoadingComplete

<Image onLoadingComplete={(img) => console.log(img.naturalWidth)} />

Advertencia: Obsoleto desde Next.js 14 en favor de onLoad.

Una función de callback que se invoca una vez que la imagen se carga completamente y se ha eliminado el marcador de posición.

La función de callback se llamará con un argumento, una referencia al elemento <img> subyacente.

onLoad

<Image onLoad={(e) => console.log(e.target.naturalWidth)} />

Una función de callback que se invoca una vez que la imagen se carga completamente y se ha eliminado el marcador de posición.

La función de callback se llamará con un argumento, el Evento que tiene un target que referencia al elemento <img> subyacente.

onError

<Image onError={(e) => console.error(e.target.id)} />

Una función de callback que se invoca si la imagen falla al cargar.

loading

Recomendación: Esta propiedad está pensada solo para casos de uso avanzados. Cambiar una imagen para cargar con eager normalmente afectará el rendimiento. Recomendamos usar la propiedad priority en su lugar, que precargará la imagen de forma eager.

loading = 'lazy' // {lazy} | {eager}

El comportamiento de carga de la imagen. Por defecto es lazy.

Cuando es lazy, se difiere la carga de la imagen hasta que alcanza una distancia calculada desde el viewport.

Cuando es eager, la imagen se carga inmediatamente.

Aprende más sobre el atributo loading.

blurDataURL

Una Data URL que se usará como imagen de placeholder antes de que la imagen src se cargue correctamente. Solo tiene efecto cuando se combina con placeholder="blur".

Debe ser una imagen codificada en base64. Se ampliará y difuminará, por lo que se recomienda una imagen muy pequeña (10px o menos). Incluir imágenes más grandes como placeholders puede afectar el rendimiento de tu aplicación.

Pruébalo:

También puedes generar una Data URL de color sólido para que coincida con la imagen.

unoptimized

unoptimized = {false} // {false} | {true}

Cuando es true, la imagen fuente se servirá tal cual sin cambiar calidad, tamaño o formato. Por defecto es false.

import Image from 'next/image'

const UnoptimizedImage = (props) => {
  return <Image {...props} unoptimized />
}

Desde Next.js 12.3.0, esta propiedad puede asignarse a todas las imágenes actualizando next.config.js con la siguiente configuración:

next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
}

overrideSrc

Cuando se proporciona el prop src al componente <Image>, tanto los atributos srcset como src se generan automáticamente para el <img> resultante.

input.js
<Image src="/me.jpg" />
output.html
<img
  srcset="
    /_next/image?url=%2Fme.jpg&w=640&q=75 1x,
    /_next/image?url=%2Fme.jpg&w=828&q=75 2x
  "
  src="/_next/image?url=%2Fme.jpg&w=828&q=75"
/>

En algunos casos, no es deseable que se genere el atributo src y puedes querer sobrescribirlo usando el prop overrideSrc.

Por ejemplo, al actualizar un sitio web existente de <img> a <Image>, puedes querer mantener el mismo atributo src para fines de SEO como el ranking de imágenes o evitar recrawling.

input.js
<Image src="/me.jpg" overrideSrc="/override.jpg" />
output.html
<img
  srcset="
    /_next/image?url=%2Fme.jpg&w=640&q=75 1x,
    /_next/image?url=%2Fme.jpg&w=828&q=75 2x
  "
  src="/override.jpg"
/>

decoding

Una sugerencia al navegador indicando si debe esperar a que la imagen se decodifique antes de presentar otras actualizaciones de contenido o no. Por defecto es async.

Los valores posibles son los siguientes:

  • async - Decodifica la imagen de forma asíncrona y permite que otro contenido se renderice antes de que complete.
  • sync - Decodifica la imagen de forma síncrona para presentación atómica con otro contenido.
  • auto - Sin preferencia por el modo de decodificación; el navegador decide qué es mejor.

Aprende más sobre el atributo decoding.

Otros Props

Otras propiedades en el componente <Image /> se pasarán al elemento img subyacente con excepción de las siguientes:

Opciones de Configuración

Además de los props, puedes configurar el Componente de Imagen en next.config.js. Las siguientes opciones están disponibles:

localPatterns

Opcionalmente puedes configurar localPatterns en tu archivo next.config.js para permitir que se optimicen rutas específicas y bloquear todas las demás.

next.config.js
module.exports = {
  images: {
    localPatterns: [
      {
        pathname: '/assets/images/**',
        search: '',
      },
    ],
  },
}

Bueno saber: El ejemplo anterior asegurará que la propiedad src de next/image debe comenzar con /assets/images/ y no debe tener una cadena de consulta. Intentar optimizar cualquier otra ruta responderá con 400 Bad Request.

remotePatterns

Para proteger tu aplicación de usuarios maliciosos, se requiere configuración para usar imágenes externas. Esto asegura que solo imágenes externas de tu cuenta puedan servirse desde la API de Optimización de Imágenes de Next.js. Estas imágenes externas pueden configurarse con la propiedad remotePatterns en tu archivo next.config.js, como se muestra a continuación:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        port: '',
        pathname: '/account123/**',
        search: '',
      },
    ],
  },
}

Bueno saber: El ejemplo anterior asegurará que la propiedad src de next/image debe comenzar con https://example.com/account123/ y no debe tener una cadena de consulta. Cualquier otro protocolo, hostname, puerto o ruta no coincidente responderá con 400 Bad Request.

A continuación un ejemplo de la propiedad remotePatterns en el archivo next.config.js usando un patrón wildcard en hostname:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.example.com',
        port: '',
        search: '',
      },
    ],
  },
}

Bueno saber: El ejemplo anterior asegurará que la propiedad src de next/image debe comenzar con https://img1.example.com o https://me.avatar.example.com o cualquier número de subdominios. No puede tener un puerto o cadena de consulta. Cualquier otro protocolo o hostname no coincidente responderá con 400 Bad Request.

Los patrones wildcard pueden usarse tanto para pathname como hostname y tienen la siguiente sintaxis:

  • * coincide con un solo segmento de ruta o subdominio
  • ** coincide con cualquier número de segmentos de ruta al final o subdominios al principio

La sintaxis ** no funciona en medio del patrón.

Bueno saber: Al omitir protocol, port, pathname o search entonces se implica el wildcard **. Esto no se recomienda porque puede permitir que actores maliciosos optimicen URLs que no tenías intención.

A continuación un ejemplo de la propiedad remotePatterns en el archivo next.config.js usando search:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'assets.example.com',
        search: '?v=1727111025337',
      },
    ],
  },
}

Bueno saber: El ejemplo anterior asegurará que la propiedad src de next/image debe comenzar con https://assets.example.com y debe tener exactamente la cadena de consulta ?v=1727111025337. Cualquier otro protocolo o cadena de consulta responderá con 400 Bad Request.

domains

Advertencia: Obsoleto desde Next.js 14 en favor de remotePatterns estrictos para proteger tu aplicación de usuarios maliciosos. Solo usa domains si eres dueño de todo el contenido servido desde el dominio.

Similar a remotePatterns, la configuración domains puede usarse para proporcionar una lista de hostnames permitidos para imágenes externas.

Sin embargo, la configuración domains no soporta coincidencia de patrones wildcard y no puede restringir protocolo, puerto o pathname.

A continuación un ejemplo de la propiedad domains en el archivo next.config.js:

next.config.js
module.exports = {
  images: {
    domains: ['assets.acme.com'],
  },
}

loaderFile

Si deseas usar un proveedor en la nube para optimizar imágenes en lugar de usar la API de Optimización de Imágenes integrada de Next.js, puedes configurar loaderFile en tu next.config.js como sigue:

next.config.js
module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './my/image/loader.js',
  },
}

Esto debe apuntar a un archivo relativo a la raíz de tu aplicación Next.js. El archivo debe exportar una función por defecto que retorne una cadena, por ejemplo:

my/image/loader.js
export default function myImageLoader({ src, width, quality }) {
  return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}

Alternativamente, puedes usar el prop loader para configurar cada instancia de next/image.

Ejemplos:

Avanzado

La siguiente configuración es para casos de uso avanzados y generalmente no es necesaria. Si eliges configurar las propiedades a continuación, anularás cualquier cambio a los valores por defecto de Next.js en futuras actualizaciones.

deviceSizes

Si conoces los anchos de dispositivo esperados de tus usuarios, puedes especificar una lista de breakpoints de ancho de dispositivo usando la propiedad deviceSizes en next.config.js. Estos anchos se usan cuando el componente next/image usa el prop sizes para asegurar que se sirva la imagen correcta para el dispositivo del usuario.

Si no se proporciona configuración, se usa el siguiente valor por defecto.

next.config.js
module.exports = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
}

imageSizes

Puedes especificar una lista de anchos de imagen usando la propiedad images.imageSizes en tu archivo next.config.js. Estos anchos se concatenan con el array de device sizes para formar el array completo de tamaños usados para generar los srcset de imágenes.

La razón por la que hay dos listas separadas es que imageSizes solo se usa para imágenes que proporcionan un prop sizes, lo que indica que la imagen es menor que el ancho completo de la pantalla. Por lo tanto, los tamaños en imageSizes deben ser todos menores que el tamaño más pequeño en deviceSizes.

Si no se proporciona configuración, se usa el siguiente valor por defecto.

next.config.js
module.exports = {
  images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
  },
}

qualities

La API de Optimización de Imágenes por defecto permitirá automáticamente todas las calidades de 1 a 100. Si deseas restringir las calidades permitidas, puedes agregar configuración a next.config.js.

next.config.js
module.exports = {
  images: {
    qualities: [25, 50, 75],
  },
}

En el ejemplo anterior, solo se permiten tres calidades: 25, 50 y 75. Si el prop quality no coincide con un valor en este array, la imagen fallará con 400 Bad Request.

formats

La API de Optimización de Imágenes por defecto detectará automáticamente los formatos de imagen soportados por el navegador a través del encabezado Accept de la solicitud.

Si el encabezado Accept coincide con más de uno de los formatos configurados, se usa la primera coincidencia en el array. Por lo tanto, el orden del array importa. Si no hay coincidencia (o la imagen fuente es animada), la API de Optimización de Imágenes recurrirá al formato original de la imagen.

Si no se proporciona configuración, se usa el siguiente valor por defecto.

next.config.js
module.exports = {
  images: {
    formats: ['image/webp'],
  },
}

Puedes habilitar soporte para AVIF con la siguiente configuración.

next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
}

Bueno saber:

  • AVIF generalmente tarda un 20% más en codificarse pero comprime un 20% más pequeño comparado con WebP. Esto significa que la primera vez que se solicita una imagen, normalmente será más lento y luego las solicitudes posteriores que están cacheadas serán más rápidas.
  • Si autoalojas con un Proxy/CDN frente a Next.js, debes configurar el Proxy para reenviar el encabezado Accept.

Comportamiento de Caché

Lo siguiente describe el algoritmo de caché para el loader por defecto. Para todos los demás loaders, consulta la documentación de tu proveedor en la nube.

Las imágenes se optimizan dinámicamente al solicitarse y se almacenan en el directorio <distDir>/cache/images. El archivo de imagen optimizado se servirá para solicitudes posteriores hasta que se alcance la expiración. Cuando se hace una solicitud que coincide con un archivo cachead

dangerouslyAllowSVG

El cargador (loader) predeterminado no optimiza imágenes SVG por varias razones. Primero, SVG es un formato vectorial, lo que significa que puede redimensionarse sin pérdida de calidad. Segundo, SVG tiene muchas características similares a HTML/CSS, lo que puede generar vulnerabilidades sin los encabezados adecuados de Política de Seguridad de Contenido (CSP).

Por lo tanto, recomendamos usar la propiedad unoptimized cuando se sabe que la propiedad src es un SVG. Esto ocurre automáticamente cuando src termina en ".svg".

Sin embargo, si necesitas servir imágenes SVG con la API predeterminada de Optimización de Imágenes, puedes configurar dangerouslyAllowSVG en tu next.config.js:

next.config.js
module.exports = {
  images: {
    dangerouslyAllowSVG: true,
    contentDispositionType: 'attachment',
    contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
  },
}

Además, se recomienda encarecidamente configurar también contentDispositionType para forzar al navegador a descargar la imagen, así como contentSecurityPolicy para evitar que se ejecuten scripts incrustados en la imagen.

Imágenes animadas

El cargador (loader) predeterminado omitirá automáticamente la Optimización de Imágenes para imágenes animadas y servirá la imagen tal cual.

La detección automática de archivos animados es de mejor esfuerzo y admite GIF, APNG y WebP. Si deseas omitir explícitamente la Optimización de Imágenes para una imagen animada específica, usa la propiedad unoptimized.

Imágenes responsivas

El srcset generado predeterminado contiene imágenes 1x y 2x para admitir diferentes densidades de píxeles del dispositivo. Sin embargo, es posible que desees renderizar una imagen responsiva que se estire con el viewport. En ese caso, deberás configurar sizes junto con style (o className).

Puedes renderizar una imagen responsiva utilizando uno de los siguientes métodos.

Imagen responsiva usando una importación estática

Si la imagen de origen no es dinámica, puedes importarla estáticamente para crear una imagen responsiva:

components/author.js
import Image from 'next/image'
import me from '../photos/me.jpg'

export default function Author() {
  return (
    <Image
      src={me}
      alt="Foto del autor"
      sizes="100vw"
      style={{
        width: '100%',
        height: 'auto',
      }}
    />
  )
}

Pruébalo:

Imagen responsiva con relación de aspecto

Si la imagen de origen es dinámica o una URL remota, también deberás proporcionar width y height para establecer la relación de aspecto correcta de la imagen responsiva:

components/page.js
import Image from 'next/image'

export default function Page({ photoUrl }) {
  return (
    <Image
      src={photoUrl}
      alt="Foto del autor"
      sizes="100vw"
      style={{
        width: '100%',
        height: 'auto',
      }}
      width={500}
      height={300}
    />
  )
}

Pruébalo:

Imagen responsiva con fill

Si no conoces la relación de aspecto, deberás configurar la propiedad fill y establecer position: relative en el elemento padre. Opcionalmente, puedes configurar el estilo object-fit según el comportamiento deseado de estiramiento vs recorte:

app/page.js
import Image from 'next/image'

export default function Page({ photoUrl }) {
  return (
    <div style={{ position: 'relative', width: '300px', height: '500px' }}>
      <Image
        src={photoUrl}
        alt="Foto del autor"
        sizes="300px"
        fill
        style={{
          objectFit: 'contain',
        }}
      />
    </div>
  )
}

Pruébalo:

CSS de detección de tema

Si deseas mostrar una imagen diferente para los modos claro y oscuro, puedes crear un nuevo componente que envuelva dos componentes <Image> y muestre el correcto basado en una consulta de medios CSS.

components/theme-image.module.css
.imgDark {
  display: none;
}

@media (prefers-color-scheme: dark) {
  .imgLight {
    display: none;
  }
  .imgDark {
    display: unset;
  }
}
import styles from './theme-image.module.css'
import Image, { ImageProps } from 'next/image'

type Props = Omit<ImageProps, 'src' | 'priority' | 'loading'> & {
  srcLight: string
  srcDark: string
}

const ThemeImage = (props: Props) => {
  const { srcLight, srcDark, ...rest } = props

  return (
    <>
      <Image {...rest} src={srcLight} className={styles.imgLight} />
      <Image {...rest} src={srcDark} className={styles.imgDark} />
    </>
  )
}
import styles from './theme-image.module.css'
import Image from 'next/image'

const ThemeImage = (props) => {
  const { srcLight, srcDark, ...rest } = props

  return (
    <>
      <Image {...rest} src={srcLight} className={styles.imgLight} />
      <Image {...rest} src={srcDark} className={styles.imgDark} />
    </>
  )
}

Nota importante: El comportamiento predeterminado de loading="lazy" asegura que solo se cargue la imagen correcta. No puedes usar priority o loading="eager" porque eso haría que ambas imágenes se carguen. En su lugar, puedes usar fetchPriority="high".

Pruébalo:

getImageProps

Para casos de uso más avanzados, puedes llamar a getImageProps() para obtener las props que se pasarían al elemento <img> subyacente y, en su lugar, pasarlas a otro componente, estilo, canvas, etc.

Esto también evita llamar a useState() de React, lo que puede mejorar el rendimiento, pero no se puede usar con la propiedad placeholder porque el marcador de posición nunca se eliminará.

Detección de tema con <picture>

Si deseas mostrar una imagen diferente para los modos claro y oscuro, puedes usar el elemento <picture> para mostrar una imagen diferente basada en el esquema de color preferido del usuario.

app/page.js
import { getImageProps } from 'next/image'

export default function Page() {
  const common = { alt: 'Ejemplo de tema', width: 800, height: 400 }
  const {
    props: { srcSet: dark },
  } = getImageProps({ ...common, src: '/dark.png' })
  const {
    props: { srcSet: light, ...rest },
  } = getImageProps({ ...common, src: '/light.png' })

  return (
    <picture>
      <source media="(prefers-color-scheme: dark)" srcSet={dark} />
      <source media="(prefers-color-scheme: light)" srcSet={light} />
      <img {...rest} />
    </picture>
  )
}

Dirección de arte

Si deseas mostrar una imagen diferente para móvil y escritorio, a veces llamado Dirección de arte, puedes proporcionar diferentes props src, width, height y quality a getImageProps().

app/page.js
import { getImageProps } from 'next/image'

export default function Home() {
  const common = { alt: 'Ejemplo de dirección de arte', sizes: '100vw' }
  const {
    props: { srcSet: desktop },
  } = getImageProps({
    ...common,
    width: 1440,
    height: 875,
    quality: 80,
    src: '/desktop.jpg',
  })
  const {
    props: { srcSet: mobile, ...rest },
  } = getImageProps({
    ...common,
    width: 750,
    height: 1334,
    quality: 70,
    src: '/mobile.jpg',
  })

  return (
    <picture>
      <source media="(min-width: 1000px)" srcSet={desktop} />
      <source media="(min-width: 500px)" srcSet={mobile} />
      <img {...rest} style={{ width: '100%', height: 'auto' }} />
    </picture>
  )
}

Fondo CSS

Incluso puedes convertir la cadena srcSet a la función CSS image-set() para optimizar una imagen de fondo.

app/page.js
import { getImageProps } from 'next/image'

function getBackgroundImage(srcSet = '') {
  const imageSet = srcSet
    .split(', ')
    .map((str) => {
      const [url, dpi] = str.split(' ')
      return `url("${url}") ${dpi}`
    })
    .join(', ')
  return `image-set(${imageSet})`
}

export default function Home() {
  const {
    props: { srcSet },
  } = getImageProps({ alt: '', width: 128, height: 128, src: '/img.png' })
  const backgroundImage = getBackgroundImage(srcSet)
  const style = { height: '100vh', width: '100vw', backgroundImage }

  return (
    <main style={style}>
      <h1>Hola Mundo</h1>
    </main>
  )
}

Errores conocidos del navegador

El componente next/image usa la carga diferida (lazy loading) nativa del navegador, que puede recurrir a la carga ansiosa para navegadores antiguos anteriores a Safari 15.4. Al usar el marcador de posición de desenfoque (blur-up), navegadores antiguos anteriores a Safari 12 recurrirán a un marcador de posición vacío. Al usar estilos con width/height en auto, es posible causar Cambio de diseño (Layout Shift) en navegadores antiguos anteriores a Safari 15 que no preservan la relación de aspecto. Para más detalles, consulta este video de MDN.

  • Safari 15 - 16.3 muestra un borde gris durante la carga. Safari 16.4 solucionó este problema. Posibles soluciones:
    • Usar CSS @supports (font: -apple-system-body) and (-webkit-appearance: none) { img[loading="lazy"] { clip-path: inset(0.6px) } }
    • Usar priority si la imagen está visible sin desplazamiento (above the fold)
  • Firefox 67+ muestra un fondo blanco durante la carga. Posibles soluciones:

Historial de Versiones

VersiónCambios
v14.2.23Se agregó la configuración qualities.
v14.2.15Se agregó la propiedad decoding y la configuración localPatterns.
v14.2.14Se agregó la propiedad remotePatterns.search.
v14.2.0Se agregó la propiedad overrideSrc.
v14.1.0getImageProps() es estable.
v14.0.0La propiedad onLoadingComplete y la configuración domains quedaron obsoletas.
v13.4.14Soporte para placeholder con data:/image....
v13.2.0Se agregó la configuración contentDispositionType.
v13.0.6Se agregó la propiedad ref.
v13.0.0La importación next/image se renombró a next/legacy/image. La importación next/future/image se renombró a next/image. Hay disponible un codemod para renombrar las importaciones de forma segura y automática. Se eliminó el envoltorio <span>. Se eliminaron las propiedades layout, objectFit, objectPosition, lazyBoundary, lazyRoot. alt es obligatorio. onLoadingComplete recibe referencia al elemento img. Se eliminó la configuración del loader integrado.
v12.3.0Las configuraciones remotePatterns y unoptimized son estables.
v12.2.0Se agregaron remotePatterns experimental y configuración experimental unoptimized. Se eliminó layout="raw".
v12.1.1Se agregó la propiedad style. Soporte experimental para layout="raw".
v12.1.0Se agregaron las configuraciones dangerouslyAllowSVG y contentSecurityPolicy.
v12.0.9Se agregó la propiedad lazyRoot.
v12.0.0Se agregó la configuración formats.
Se agregó soporte para AVIF.
El envoltorio <div> cambió a <span>.
v11.1.0Se agregaron las propiedades onLoadingComplete y lazyBoundary.
v11.0.0Soporte para src con importación estática.
Se agregó la propiedad placeholder.
Se agregó la propiedad blurDataURL.
v10.0.5Se agregó la propiedad loader.
v10.0.1Se agregó la propiedad layout.
v10.0.0Se introdujo next/image.