UPDATE: As of Nextjs 13.5 a new experimental function unstable_getImgProps() was added to support advanced use cases without using the component directly, including the picture Tag:
import { unstable_getImgProps as getImgProps } from 'next/image';
export default function Page() {
const common = { alt: 'Hero', width: 800, height: 400 };
const {
props: { srcSet: dark },
} = getImgProps({ ...common, src: '/dark.png' });
const {
props: { srcSet: light, ...rest },
} = getImgProps({ ...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>
);
}
https://nextjs.org/blog/next-13-5#nextimage-improvements
The new version of Next Image component removes a lot of the extraneous HTML and styles and allows full flexibility of the img
tag. With that new improvement in the component we can use the picture tag and the image component as normal.
Plus, Web.dev explains the way the picture element works really well: https://web.dev/learn/design/picture-element/
In the same way that srcset builds upon the src attribute, the picture element builds upon the img element. The picture element wraps around an img element.
If there is no img element nested inside the picture element, the picture element won't work.
Like the srcset attribute, the picture element will update the value of the src attribute in that img element. The difference is that where the srcset attribute gives suggestions to the browser, the picture element gives commands. This gives you control.
So, understanding that the picture
element is just a wrapper of the img
element which the browser still requires, and using the new version of next/image (Nextjs v. 13), you can write it as:
import Image from "next/image";
<picture>
<source srcset=".." media="..."/>
<Image src="..." height="..." width="..." alt="..." />
</picture>