Skip to content

图片与外部资源的异步解码

decoding 属性控制浏览器解码图片的方式,可以减少解码过程对主线程的阻塞,提升页面渲染性能。本节将介绍 decoding 的三个值及其适用场景。

前置知识

阅读本节前,建议先了解:object 嵌入对象

基础概念

当浏览器下载完一张图片后,还需要将压缩的图片数据"解码"为像素数据才能渲染到屏幕上。对于大图片(如高分辨率照片),解码过程可能需要数十毫秒,这段时间内主线程被阻塞,可能导致页面卡顿。

HTML5 的 decoding 属性允许开发者告诉浏览器是否应该异步解码图片,从而避免解码过程阻塞页面渲染。

语法

decoding 属性

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>decoding 属性</title>
</head>
<body>
  <h1>decoding 属性</h1>

  <!-- auto:浏览器自行决定 -->
  <img src="photo.jpg" alt="照片" decoding="auto" width="600" height="400">

  <br>

  <!-- sync:同步解码(阻塞主线程) -->
  <img src="icon.png" alt="图标" decoding="sync" width="32" height="32">

  <br>

  <!-- async:异步解码(不阻塞主线程) -->
  <img src="large-photo.jpg" alt="大图" decoding="async" width="1200" height="800">
</body>
</html>

详细说明

decoding 值详解

行为适用场景
auto浏览器自行决定(默认)大多数情况
sync同步解码,阻塞渲染小图标、首屏关键图片
async异步解码,不阻塞渲染大图片、非关键图片

何时使用 async

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>decoding async</title>
</head>
<body>
  <h1>何时使用 decoding="async"</h1>

  <!--
    适合使用 async 的场景:
    - 图片不在首屏(用户需要滚动才能看到)
    - 图片尺寸较大(解码时间较长)
    - 图片不是首屏渲染的关键元素
  -->

  <!-- 首屏大图:async 可以减少解码对渲染的阻塞 -->
  <img src="hero-banner.jpg"
       alt="横幅大图"
       decoding="async"
       loading="lazy"
       width="1200" height="400">

  <!-- 文章配图:异步解码 -->
  <img src="article-photo.jpg"
       alt="文章配图"
       decoding="async"
       loading="lazy"
       width="800" height="600">

  <!--
    适合使用 sync 的场景:
    - 小尺寸图片(解码时间极短,异步无意义)
    - 首屏关键内容(需要确保立即显示)
  -->

  <!-- 小图标:sync 确保立即显示 -->
  <img src="logo.png" alt="Logo" decoding="sync" width="120" height="40">
  <img src="star-icon.png" alt="星级" decoding="sync" width="16" height="16">
</body>
</html>

decoding 与 loading 的配合

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>decoding + loading</title>
</head>
<body>
  <h1>decoding 与 loading 配合</h1>

  <!-- 最佳组合:懒加载 + 异步解码 -->
  <img src="large-image.jpg"
       alt="大图"
       loading="lazy"
       decoding="async"
       width="1200" height="800">

  <!-- 首屏关键图片:立即加载 + 自动解码 -->
  <img src="hero.jpg"
       alt="首屏大图"
       width="1200" height="400">
  <!-- decoding 默认就是 auto,无需显式设置 -->

  <!-- 全部优化属性组合 -->
  <img src="photo.jpg"
       alt="优化后的图片"
       srcset="photo-400w.jpg 400w, photo-800w.jpg 800w"
       sizes="(max-width: 600px) 100vw, 800px"
       loading="lazy"
       decoding="async"
       width="800" height="600">
</body>
</html>

性能优化属性组合

属性作用何时使用
loading="lazy"延迟加载非首屏图片
decoding="async"异步解码大图片、非关键图片
width/height防止 CLS所有图片
fetchpriority="high"高优先级获取关键图片(如 LCP)
fetchpriority="low"低优先级获取非关键图片

实战示例

性能优化的图片画廊

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>性能优化画廊</title>
  <style>
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      max-width: 900px;
      margin: 0 auto;
      padding: 20px;
    }
    .gallery {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
      gap: 16px;
    }
    .gallery img {
      width: 100%;
      height: 200px;
      object-fit: cover;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <h1>高性能图片画廊</h1>

  <div class="gallery">
    <img src="photo1.jpg" alt="作品 1" width="400" height="300"
         loading="lazy" decoding="async">
    <img src="photo2.jpg" alt="作品 2" width="400" height="300"
         loading="lazy" decoding="async">
    <img src="photo3.jpg" alt="作品 3" width="400" height="300"
         loading="lazy" decoding="async">
    <img src="photo4.jpg" alt="作品 4" width="400" height="300"
         loading="lazy" decoding="async">
    <img src="photo5.jpg" alt="作品 5" width="400" height="300"
         loading="lazy" decoding="async">
    <img src="photo6.jpg" alt="作品 6" width="400" height="300"
         loading="lazy" decoding="async">
  </div>
</body>
</html>

注意事项

  • decoding="async" 可能导致图片在解码完成前显示为空白
  • 小图片(<10KB)使用 decoding="async" 意义不大
  • decoding 属性适用于 <img> 标签
  • 浏览器对 decoding 的实现方式不同,效果可能有差异
  • fetchpriority 属性与 decoding 是互补的,不是替代关系

最佳实践

  • 非首屏的大图片使用 decoding="async" + loading="lazy"
  • 首屏关键小图标使用 decoding="sync" 确保立即显示
  • 大部分图片使用默认的 decoding="auto" 即可
  • 结合 width/height 属性防止 CLS
  • 使用 Lighthouse 测试解码对性能的影响

下一节

继续学习:canvas 画布基础

参考链接