Menu

<Image>

示例

本 API 参考将帮助你了解如何使用 Image 组件可用的 属性配置选项。关于功能和用法,请参阅 Image 组件 页面。

app/page.js
import Image from 'next/image'
 
export default function Page() {
  return (
    <Image
      src="/profile.png"
      width={500}
      height={500}
      alt="作者的照片"
    />
  )
}

属性 (Props)

以下是 Image 组件可用属性的总结:

属性示例类型状态
srcsrc="/profile.png"String必需
widthwidth={500}Integer (px)必需
heightheight={500}Integer (px)必需
altalt="作者的照片"String必需
loaderloader={imageLoader}Function-
fillfill={true}Boolean-
sizessizes="(max-width: 768px) 100vw, 33vw"String-
qualityquality={80}Integer (1-100)-
prioritypriority={true}Boolean-
placeholderplaceholder="blur"String-
stylestyle={{objectFit: "contain"}}Object-
onLoadingCompleteonLoadingComplete={img => done()}Function已弃用
onLoadonLoad={event => done()}Function-
onErroronError(event => fail()}Function-
loadingloading="lazy"String-
blurDataURLblurDataURL="data:image/jpeg..."String-
overrideSrcoverrideSrc="/seo.png"String-

必需属性

Image 组件需要以下属性:srcaltwidthheight (或 fill)。

app/page.js
import Image from 'next/image'
 
export default function Page() {
  return (
    <div>
      <Image
        src="/profile.png"
        width={500}
        height={500}
        alt="作者的照片"
      />
    </div>
  )
}

src

必须是以下之一:

  • 一个静态导入的图片文件
  • 一个路径字符串。根据 loader 属性,这可以是绝对外部 URL,或内部路径。

当使用默认的 loader 时,还需要考虑以下对源图片的要求:

  • 当 src 是外部 URL 时,你还必须配置 remotePatterns
  • 当 src 是动画或不是已知格式 (JPEG、PNG、WebP、AVIF、GIF、TIFF) 时,图片将按原样提供
  • 当 src 是 SVG 格式时,除非启用了 unoptimizeddangerouslyAllowSVG,否则将被阻止

width

width 属性表示以像素为单位的图片_固有_宽度。该属性用于推断正确的图片纵横比并避免加载过程中的布局偏移。它不决定图片的渲染大小,渲染大小由 CSS 控制,类似于 HTML <img> 标签中的 width 属性。

除了静态导入的图片或带有 fill 属性 的图片外,该属性是必需的。

height

height 属性表示以像素为单位的图片_固有_高度。该属性用于推断正确的图片纵横比并避免加载过程中的布局偏移。它不决定图片的渲染大小,渲染大小由 CSS 控制,类似于 HTML <img> 标签中的 height 属性。

除了静态导入的图片或带有 fill 属性 的图片外,该属性是必需的。

值得注意的是

  • widthheight 属性一起用于确定图片的纵横比,浏览器会使用这个比例在图片加载之前预留空间。
  • 固有尺寸并不总是意味着在浏览器中的渲染尺寸,渲染尺寸将由父容器决定。例如,如果父容器小于固有尺寸,图片将被缩小以适应容器。
  • 当宽度和高度未知时,你可以使用 fill 属性。

alt

alt 属性用于为屏幕阅读器和搜索引擎描述图片。它也是在图片被禁用或加载图片出错时的后备文本。

它应该包含能够在不改变页面含义的情况下替代图片的文本。它不是用来补充图片的,也不应重复已经在图片上方或下方标题中提供的信息。

如果图片是纯装饰性的不是面向用户的alt 属性应该是一个空字符串 (alt="")。

了解更多

可选属性

<Image /> 组件除了必需属性外,还接受许多其他属性。本节描述 Image 组件最常用的属性。关于更少使用的属性的详细信息,请参见高级属性部分。

loader

用于解析图片 URL 的自定义函数。

loader 是一个返回图片 URL 字符串的函数,该函数接收以下参数:

以下是使用自定义 loader 的示例:

'use client'
 
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="作者的照片"
      width={500}
      height={500}
    />
  )
}

值得注意的是:使用接受函数的属性(如 loader)需要使用 客户端组件 来序列化提供的函数。

或者,你可以使用 next.config.js 中的 loaderFile 配置来配置应用中每个 next/image 实例,而无需传递属性。

fill

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

一个布尔值,使图片填充父元素,这在 widthheight 未知时很有用。

父元素_必须_指定 position: "relative"position: "fixed"position: "absolute" 样式。

默认情况下,img 元素将自动被赋予 position: "absolute" 样式。

如果没有应用任何样式,图片将会拉伸以适应容器。你可能更喜欢设置 object-fit: "contain" 来使图片在保持纵横比的情况下进行信箱处理以适应容器。

或者,使用 object-fit: "cover" 将导致图片填充整个容器并在保持纵横比的情况下进行裁剪。

更多信息,另请参见:

sizes

一个类似于媒体查询的字符串,提供关于图片在不同断点下的宽度信息。对于使用 fill设置为响应式大小的样式的图片来说,sizes 的值会极大地影响性能。

sizes 属性有两个重要用途:

  • 首先,浏览器使用 sizes 的值来决定从 next/image 自动生成的 srcset 中下载哪个尺寸的图片。当浏览器做出选择时,它还不知道图片在页面上的大小,因此它会选择与视口大小相同或更大的图片。sizes 属性允许你告诉浏览器图片实际上会比全屏小。如果你没有为带有 fill 属性的图片指定 sizes 值,将使用默认值 100vw(全屏宽度)。

  • 其次,sizes 属性会改变自动生成的 srcset 值的行为。如果没有 sizes 值,将生成一个适用于固定大小图片的小 srcset(1x/2x/等)。如果定义了 sizes,将生成一个适用于响应式图片的大 srcset(640w/750w/等)。如果 sizes 属性包含类似 50vw 这样表示视口宽度百分比的值,则 srcset 将被裁剪,不包含任何永远不会需要的过小值。

例如,如果你知道你的样式会导致图片在移动设备上全宽显示,在平板电脑上使用 2 列布局,在桌面显示器上使用 3 列布局,你应该包含如下的 sizes 属性:

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>
  )
}

这个 sizes 示例可能对性能指标产生巨大影响。没有 33vw sizes,从服务器选择的图片宽度将是实际需要的 3 倍。因为文件大小与宽度的平方成正比,如果没有 sizes,用户将下载一个比必要大 9 倍的图片。

了解更多关于 srcsetsizes 的信息:

quality

quality={75} // {number 1-100}

优化后的图片质量,一个介于 1100 之间的整数,其中 100 是最佳质量,因此文件最大。默认值为 75

priority

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

当为 true 时,图片将被视为高优先级并预加载。对使用 priority 的图片会自动禁用延迟加载。如果同时使用了 loading 属性并设置为 lazy,则不能使用 priority 属性。loading 属性仅用于高级用例。当需要 priority 时,请移除 loading

你应该对任何被检测为最大内容绘制 (LCP) 元素的图片使用 priority 属性。可能有多个优先级图片是合适的,因为不同的图片可能是不同视口大小的 LCP 元素。

应该仅用于首屏可见的图片。默认为 false

placeholder

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

图片加载时使用的占位符。可能的值是 bluremptydata:image/...。默认为 empty

当为 blur 时,blurDataURL 属性将被用作占位符。如果 src 是来自静态导入的对象,且导入的图片是 .jpg.png.webp.avif,则 blurDataURL 将被自动填充,除非图片被检测为动画。

对于动态图片,你必须提供 blurDataURL 属性。像 Plaiceholder 这样的解决方案可以帮助生成 base64

当为 data:image/... 时,Data URL 将在图片加载时用作占位符。

当为 empty 时,图片加载时将没有占位符,只有空白空间。

尝试一下:

高级属性

在某些情况下,你可能需要更高级的用法。<Image /> 组件可选地接受以下高级属性。

style

允许向底层图片元素传递 CSS 样式。

components/ProfileImage.js
const imageStyle = {
  borderRadius: '50%',
  border: '1px solid #fff',
}
 
export default function ProfileImage() {
  return <Image src="..." style={imageStyle} />
}

请记住,必需的宽度和高度属性可能会与你的样式产生交互。如果你使用样式来修改图片的宽度,你还应该将其高度样式设置为 auto 以保持其固有纵横比,否则你的图片将变形。

onLoadingComplete

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

警告:自 Next.js 14 起已弃用,推荐使用 onLoad

一个回调函数,在图片完全加载且 placeholder 被移除后调用。

回调函数将接收一个参数,即对底层 <img> 元素的引用。

值得注意的是:使用接受函数的属性(如 onLoadingComplete)需要使用客户端组件来序列化提供的函数。

onLoad

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

一个回调函数,在图片完全加载且 placeholder 被移除后调用。

回调函数将接收一个参数,即事件对象,其 target 引用底层 <img> 元素。

值得注意的是:使用接受函数的属性(如 onLoad)需要使用客户端组件来序列化提供的函数。

onError

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

一个在图片加载失败时调用的回调函数。

值得注意的是:使用接受函数的属性(如 onError)需要使用客户端组件来序列化提供的函数。

loading

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

图片的加载行为。默认为 lazy

当为 lazy 时,延迟加载图片,直到它达到与视口的计算距离。

当为 eager 时,立即加载图片。

了解更多关于 loading 属性的信息。

blurDataURL

src 图片成功加载之前用作占位符图片的 Data URL。仅当与 placeholder="blur" 组合使用时才生效。

必须是 base64 编码的图片。它将被放大和模糊,因此建议使用非常小的图片(10px 或更小)。将较大的图片作为占位符可能会损害应用性能。

尝试一下:

你还可以生成纯色 Data URL 来匹配图片。

unoptimized

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

当为 true 时,源图片将按原样提供,而不是改变质量、大小或格式。默认为 false

import Image from 'next/image'
 
const UnoptimizedImage = (props) => {
  return <Image {...props} unoptimized />
}

从 Next.js 12.3.0 起,可以通过在 next.config.js 中使用以下配置来为所有图片分配此属性:

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

overrideSrc

当向 <Image> 组件提供 src 属性时,会自动为生成的 <img> 生成 srcsetsrc 属性。

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"
/>

在某些情况下,你可能不希望生成 src 属性,而是希望使用 overrideSrc 属性来覆盖它。

例如,当将现有网站从 <img> 升级到 <Image> 时,你可能希望为了 SEO 目的(如图片排名或避免重新抓取)而保持相同的 src 属性。

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

一个向浏览器提示是否应该等待图片解码完成才呈现其他内容更新的属性。默认为 async

可能的值如下:

  • async - 异步解码图片,允许在完成之前渲染其他内容。
  • sync - 同步解码图片,以便与其他内容同时呈现。
  • auto - 对解码模式没有偏好,由浏览器决定最佳方式。

了解更多关于 decoding 属性的信息。

其他属性

除了以下特例外,<Image /> 组件上的其他属性都将传递给底层的 img 元素:

配置选项

除了属性外,你还可以在 next.config.js 中配置 Image 组件。以下选项可用:

localPatterns

你可以在 next.config.js 文件中配置 localPatterns 以允许优化特定路径并阻止所有其他路径。

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

值得注意的是:上面的示例将确保 next/imagesrc 属性必须以 /assets/images/ 开头,并且不能有查询字符串。尝试优化任何其他路径都将返回 400 Bad Request。

remotePatterns

为了保护你的应用免受恶意用户的侵害,使用外部图片时需要配置。这确保只有来自你账户的外部图片可以从 Next.js 图片优化 API 提供服务。这些外部图片可以在 next.config.js 文件中使用 remotePatterns 属性进行配置,如下所示:

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

值得注意的是:上面的示例将确保 next/imagesrc 属性必须以 https://example.com/account123/ 开头,并且不能有查询字符串。任何其他协议、主机名、端口或不匹配的路径都将返回 400 Bad Request。

以下是在 next.config.js 文件中使用主机名通配符模式的 remotePatterns 属性示例:

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

值得注意的是:上面的示例将确保 next/imagesrc 属性必须以 https://img1.example.comhttps://me.avatar.example.com 或任意数量的子域名开头。它不能有端口或查询字符串。任何其他协议或不匹配的主机名都将返回 400 Bad Request。

pathnamehostname 都可以使用通配符模式,语法如下:

  • * 匹配单个路径段或子域名
  • ** 匹配末尾的任意数量路径段或开头的子域名

** 语法不能在模式中间使用。

值得注意的是:当省略 protocolportpathnamesearch 时,默认使用通配符 **。不建议这样做,因为这可能允许恶意行为者优化你不打算优化的 URL。

以下是在 next.config.js 文件中使用 searchremotePatterns 属性示例:

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

值得注意的是:上面的示例将确保 next/imagesrc 属性必须以 https://assets.example.com 开头,并且必须具有完全相同的查询字符串 ?v=1727111025337。任何其他协议或查询字符串都将返回 400 Bad Request。

domains

警告:自 Next.js 14 起已弃用,推荐使用严格的 remotePatterns 以保护你的应用免受恶意用户的侵害。只有当你拥有该域名上提供的所有内容时才使用 domains

remotePatterns 类似,domains 配置可用于提供外部图片允许的主机名列表。

然而,domains 配置不支持通配符模式匹配,也不能限制协议、端口或路径名。

以下是 next.config.js 文件中的 domains 属性示例:

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

loaderFile

如果你想使用云提供商来优化图片而不是使用 Next.js 内置的图片优化 API,你可以在 next.config.js 中配置 loaderFile,如下所示:

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

这必须指向相对于 Next.js 应用根目录的文件。该文件必须导出一个返回字符串的默认函数,例如:

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

或者,你可以使用 loader 属性来配置每个 next/image 实例。

示例:

值得注意的是:自定义图片加载器文件,它接受一个函数,需要使用客户端组件来序列化提供的函数。

高级

以下配置适用于高级用例,通常不需要。如果你选择配置以下属性,你将覆盖未来更新中 Next.js 默认值的任何更改。

deviceSizes

如果你知道用户的预期设备宽度,你可以使用 next.config.js 中的 deviceSizes 属性指定设备宽度断点列表。当 next/image 组件使用 sizes 属性时,这些宽度用于确保为用户的设备提供正确的图片。

如果没有提供配置,将使用以下默认值。

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

imageSizes

你可以在 next.config.js 文件中使用 images.imageSizes 属性指定图片宽度列表。这些宽度与设备尺寸数组连接,形成用于生成图片 srcset 的完整尺寸数组。

有两个单独列表的原因是 imageSizes 仅用于提供 sizes 属性的图片,这表明图片小于屏幕的全宽。因此,imageSizes 中的尺寸都应该小于 deviceSizes 中的最小尺寸。

如果没有提供配置,将使用以下默认值。

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

formats

默认图片优化 API 将通过请求的 Accept header 自动检测浏览器支持的图片格式,以确定最佳输出格式。

如果 Accept header 匹配多个配置的格式,则使用数组中的第一个匹配项。因此,数组顺序很重要。如果没有匹配项(或源图片是动画的),图片优化 API 将回退到原始图片格式。

如果没有提供配置,将使用以下默认值。

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

你可以启用 AVIF 支持并仍然回退到 WebP,使用以下配置。

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

值得注意的是

  • AVIF 编码通常需要多 50% 的时间,但压缩后比 WebP 小 20%。这意味着第一次请求图片时通常会较慢,然后后续的缓存请求会更快。
  • 如果你在 Next.js 前面使用代理/CDN 进行自托管,你必须配置代理以转发 Accept header。

缓存行为

以下描述默认 loader 的缓存算法。对于所有其他 loader,请参考你的云提供商的文档。

图片会在请求时动态优化并存储在 <distDir>/cache/images 目录中。优化后的图片文件将用于后续请求,直到过期。当请求匹配缓存但已过期的文件时,过期的图片会立即以过期状态提供服务。然后在后台重新优化图片(也称为重新验证)并保存到缓存中,带有新的过期日期。

可以通过读取 x-nextjs-cache 响应 header 的值来确定图片的缓存状态。可能的值如下:

  • MISS - 路径不在缓存中(最多发生一次,在首次访问时)
  • STALE - 路径在缓存中但超过了重新验证时间,因此将在后台更新
  • HIT - 路径在缓存中且未超过重新验证时间

过期时间(或者说最大年龄)由 minimumCacheTTL 配置或上游图片 Cache-Control header 定义,以较大者为准。具体来说,使用 Cache-Control header 的 max-age 值。如果同时找到 s-maxagemax-age,则优先使用 s-maxagemax-age 也会传递给任何下游客户端,包括 CDN 和浏览器。

  • 当上游图片不包含 Cache-Control header 或值很低时,你可以配置 minimumCacheTTL 来增加缓存持续时间。
  • 你可以配置 deviceSizesimageSizes 来减少可能生成的图片总数。
  • 你可以配置 formats 来禁用多种格式,转而使用单一图片格式。

minimumCacheTTL

你可以配置缓存优化图片的生存时间(TTL),单位为秒。在许多情况下,使用静态图片导入会更好,它会自动对文件内容进行哈希处理,并使用 Cache-Control header 的 immutable 值永久缓存图片。

next.config.js
module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}

优化图片的过期时间(或者说最大年龄)由 minimumCacheTTL 或上游图片的 Cache-Control header 定义,以较大者为准。

如果你需要为每个图片更改缓存行为,你可以配置 headers 来设置上游图片的 Cache-Control header (例如:/some-asset.jpg,而不是 /_next/image 本身)。

目前没有机制来使缓存失效,所以最好保持 minimumCacheTTL 较低。否则你可能需要手动更改 src 属性或删除 <distDir>/cache/images

disableStaticImages

默认行为允许你导入静态文件,例如 import icon from './icon.png',然后将其传递给 src 属性。

在某些情况下,如果这个功能与其他期望导入行为不同的插件冲突,你可能希望禁用此功能。

你可以在 next.config.js 中禁用静态图片导入:

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

dangerouslyAllowSVG

默认的 loader 出于以下原因不优化 SVG 图片。首先,SVG 是一种矢量格式,意味着它可以无损调整大小。其次,SVG 具有许多与 HTML/CSS 相同的功能,如果没有适当的内容安全策略 (CSP) headers,可能会导致漏洞。

因此,我们建议在 src 属性已知为 SVG 时使用 unoptimized 属性。当 src".svg" 结尾时,这会自动发生。

然而,如果你需要用默认的图片优化 API 来服务 SVG 图片,你可以在 next.config.js 中设置 dangerouslyAllowSVG

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

此外,强烈建议设置 contentDispositionType 来强制浏览器下载图片,以及设置 contentSecurityPolicy 来防止图片中嵌入的脚本执行。

contentDispositionType

默认的 loaderContent-Disposition header 设置为 attachment 以提供额外的保护,因为 API 可以提供任意远程图片。

默认值是 attachment,这会强制浏览器在直接访问时下载图片。当 dangerouslyAllowSVG 为 true 时,这一点特别重要。

你可以选择配置 inline 以允许浏览器在直接访问时渲染图片,而不是下载它。

next.config.js
module.exports = {
  images: {
    contentDispositionType: 'inline',
  },
}

动画图片

默认的 loader 将自动绕过动画图片的图片优化,按原样提供图片。

动画文件的自动检测是尽力而为的,支持 GIF、APNG 和 WebP。如果你想明确绕过给定动画图片的图片优化,请使用 unoptimized 属性。

响应式图片

默认生成的 srcset 包含 1x2x 图片以支持不同的设备像素比。但是,你可能希望渲染一个随视口拉伸的响应式图片。在这种情况下,你需要设置 sizes 以及 style(或 className)。

你可以使用以下方法之一渲染响应式图片。

使用静态导入的响应式图片

如果源图片不是动态的,你可以静态导入来创建响应式图片:

components/author.js
import Image from 'next/image'
import me from '../photos/me.jpg'
 
export default function Author() {
  return (
    <Image
      src={me}
      alt="作者的照片"
      sizes="100vw"
      style={{
        width: '100%',
        height: 'auto',
      }}
    />
  )
}

尝试一下:

带有纵横比的响应式图片

如果源图片是动态的或远程 URL,你还需要提供 widthheight 来设置响应式图片的正确纵横比:

components/page.js
import Image from 'next/image'
 
export default function Page({ photoUrl }) {
  return (
    <Image
      src={photoUrl}
      alt="作者的照片"
      sizes="100vw"
      style={{
        width: '100%',
        height: 'auto',
      }}
      width={500}
      height={300}
    />
  )
}

尝试一下:

带有 fill 的响应式图片

如果你不知道纵横比,你需要设置 fill 属性并在父元素上设置 position: relative。还可以根据需要的拉伸与裁剪行为设置 object-fit 样式:

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="作者的照片"
        sizes="300px"
        fill
        style={{
          objectFit: 'contain',
        }}
      />
    </div>
  )
}

尝试一下:

主题检测 CSS

如果你想为浅色和深色模式显示不同的图片,你可以创建一个新组件,包装两个 <Image> 组件,并基于 CSS 媒体查询显示正确的一个。

components/theme-image.module.css
.imgDark {
  display: none;
}
 
@media (prefers-color-scheme: dark) {
  .imgLight {
    display: none;
  }
  .imgDark {
    display: unset;
  }
}
components/theme-image.tsx
TypeScript
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} />
    </>
  )
}

值得注意的是:默认的 loading="lazy" 行为确保只加载正确的图片。你不能使用 priorityloading="eager",因为这会导致两个图片都加载。相反,你可以使用 fetchPriority="high"

尝试一下:

getImageProps

对于更高级的用例,你可以调用 getImageProps() 来获取将传递给底层 <img> 元素的属性,然后将它们传递给另一个组件、样式、画布等。

这也避免了调用 React useState(),因此可以带来更好的性能,但它不能与 placeholder 属性一起使用,因为占位符永远不会被移除。

主题检测 Picture

如果你想为浅色和深色模式显示不同的图片,你可以使用 <picture> 元素根据用户的首选配色方案显示不同的图片。

app/page.js
import { getImageProps } from 'next/image'
 
export default function Page() {
  const common = { alt: '主题示例', 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>
  )
}

艺术指导

如果你想为移动端和桌面端显示不同的图片,有时称为艺术指导,你可以为 getImageProps() 提供不同的 srcwidthheightquality 属性。

app/page.js
import { getImageProps } from 'next/image'
 
export default function Home() {
  const common = { alt: '艺术指导示例', 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>
  )
}

背景 CSS

你甚至可以将 srcSet 字符串转换为 image-set() CSS 函数来优化背景图片。

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>Hello World</h1>
    </main>
  )
}

已知浏览器 Bug

这个 next/image 组件使用浏览器原生的延迟加载,对于 Safari 15.4 之前的旧版浏览器可能会回退到急切加载。当使用模糊渐现占位符时,Safari 12 之前的旧版浏览器将回退到空占位符。当使用 width/heightauto 的样式时,在不保留纵横比的 Safari 15 之前的旧版浏览器上可能会导致布局偏移。有关更多详细信息,请参阅此 MDN 视频

  • Safari 15 - 16.3 在加载时显示灰色边框。Safari 16.4 修复了这个问题。可能的解决方案:
    • 使用 CSS @supports (font: -apple-system--body) and (-webkit-appearance: none) { img[loading="lazy"] { clip-path: inset(0.6px) } }
    • 如果图片在折叠上方,使用 priority
  • Firefox 67+ 在加载时显示白色背景。可能的解决方案:

版本历史

版本更改
v15.0.0添加 decoding 属性。contentDispositionType 配置默认值改为 attachment
v14.2.0添加 overrideSrc 属性。
v14.1.0getImageProps() 稳定版。
v14.0.0废弃 onLoadingComplete 属性和 domains 配置。
v13.4.14placeholder 属性支持 data:/image...
v13.2.0添加 contentDispositionType 配置。
v13.0.6添加 ref 属性。
v13.0.0next/image 导入被重命名为 next/legacy/imagenext/future/image 导入被重命名为 next/image。提供了代码转换工具来安全自动重命名导入。移除 <span> 包装器。移除 layoutobjectFitobjectPositionlazyBoundarylazyRoot 属性。alt 是必需的。onLoadingComplete 接收 img 元素的引用。移除内置 loader 配置。
v12.3.0remotePatternsunoptimized 配置稳定版。
v12.2.0添加实验性 remotePatterns 和实验性 unoptimized 配置。移除 layout="raw"
v12.1.1添加 style 属性。添加实验性 layout="raw" 支持。
v12.1.0添加 dangerouslyAllowSVGcontentSecurityPolicy 配置。
v12.0.9添加 lazyRoot 属性。
v12.0.0添加 formats 配置。
添加 AVIF 支持。
包装器 <div> 改为 <span>
v11.1.0添加 onLoadingCompletelazyBoundary 属性。
v11.0.0src 属性支持静态导入。
添加 placeholder 属性。
添加 blurDataURL 属性。
v10.0.5添加 loader 属性。
v10.0.1添加 layout 属性。
v10.0.0引入 next/image