Todos los artículos

16 de sept de 2025

Usanddo <picture> en Next.js para imágenes responsive

Una guía breve para optimizar imágenes con el elemento picture en Next.js

Miniatura de Next.js

Introducción

En este artículo te muestro cómo usar el elemento picture en Next.js.

Si intentaste usar el elemento picture directamente en Next.js, seguramente notaste que la imagen no tiene ninguna optimización. Para resolverlo vamos a usar una función bastante nueva de Next.js: getImageProps

Crear el componente ResponsiveImage

En tu carpeta de componentes creá un archivo nuevo; yo lo voy a llamar ResponsiveImage.tsx.

Importá getImageProps y creá la base del componente:

ts
import { getImageProps } from 'next/image';

export const ResponsiveImage = () => {
return <></>;
};

Ahora voy a agregar tipos para las props del componente; por brevedad uso un tipo bastante básico.

ts
// Importamos el tipo base de las props de Image
import { getImageProps, type ImageProps } from 'next/image';

// Usamos src como fuente de verdad para la imagen
type ResponsiveImageProps = ImageProps & {
desktopSrc: string;
};

export const ResponsiveImage = ({
// Extraemos src y desktopSrc del resto de las props
src,
desktopSrc,
...props
}: ResponsiveImageProps) => {
return <></>;
};

A continuación extraemos las props de cada fuente y aplicamos las props comunes.

ts
import { getImageProps, type ImageProps } from 'next/image';

type ResponsiveImageProps = ImageProps & {
desktopSrc: string;
};

export const ResponsiveImage = ({
src,
desktopSrc,
...props
}: ResponsiveImageProps) => {
const { props: mobileImageProps } = getImageProps({ src, ...props });
const { props: desktopImageProps } = getImageProps({
src: desktopSrc,
...props,
});

return <></>;
};

Y por último usamos estos datos en el template:

ts
import { getImageProps, type ImageProps } from 'next/image';

type ResponsiveImageProps = ImageProps & {
desktopSrc: string;
};

export const ResponsiveImage = ({
src,
desktopSrc,
...props
}: ResponsiveImageProps) => {
const { props: mobileImageProps } = getImageProps({ src, ...props });
const { props: desktopImageProps } = getImageProps({
src: desktopSrc,
...props,
});

return (
<picture>
<source
// Breakpoint a partir del cual cambia la imagen
media="(min-width: 1280px)"
srcSet={desktopImageProps.srcSet}
/>

// Aplicá las props a tu imagen base (yo voy mobile first, asi que uso mobileImageProps)
<img {...mobileImageProps} />
</picture>
);
};

El uso es muy directo: se usa igual que el componente Image.

ts
<ResponsiveImage
alt="Texto alternativo"
src="/mobile-image.jpg" // Imagen base
desktopSrc="/desktop-image.jpg" // Imagen para el breakpoint de desktop
fill // Uso fill por simplicidad
// Agregá otras props de Image según necesites
/>

Poniéndolo a prueba

Abrí la página en un navegador y entrá a las herramientas de desarrollo.

  • Andá a la pestaña Network.
  • Recargá la página y observá las solicitudes de imágenes:
    • Al principio deberías ver una sola solicitud de imagen.
  • Cambiá el tamaño de la ventana del navegador:
    • Cruzá el breakpoint de 1280px para disparar el cambio de imagen.
    • Observá una nueva solicitud para la versión de desktop.
  • Recargá la página en tamaño desktop:
    • Verificá que se haga una sola solicitud de imagen (la versión de desktop).