图片懒加载

943 阅读5分钟

loading="lazy" 属性详解

loading="lazy" 是 HTML <img> 元素的一个属性,用于延迟加载图片,直到它们接近或即将进入视口(viewport)时才加载。这是一种优化网页性能的技术,可以显著减少初始页面加载时间和带宽使用。

基本用法

html

<img src="image.jpg" loading="lazy" alt="示例图片">

工作原理

  1. 当浏览器遇到带有 loading="lazy" 的图片时,不会立即下载该图片
  2. 浏览器会监控页面滚动和视口位置
  3. 当图片接近视口(通常距离视口有一定阈值)时,浏览器才开始加载图片
  4. 如果用户从未滚动到图片位置,图片可能永远不会加载

何时下载

  1. 当图片接近视口(viewport)时

    • 浏览器会计算图片与当前视口的距离
    • 当距离小于浏览器预设的阈值时触发下载
    • 不同浏览器的阈值不同:
      • Chrome:距离视口约1250px
      • Firefox:距离视口约1000px
      • Safari:与Chrome类似

浏览器支持

  • Chrome 76+(2019年8月发布)
  • Firefox 75+(2020年4月发布)
  • Edge 79+
  • Opera 63+
  • Safari 15.4+(2022年3月发布)

优点

  1. 减少初始页面加载时间:不加载视口外的图片
  2. 节省带宽:用户可能不会浏览所有内容,避免加载不必要资源
  3. 改善用户体验:优先加载可见内容
  4. 降低服务器负载:减少不必要的请求

注意事项

  1. 视口距离阈值:不同浏览器有不同的"接近视口"标准,通常为:

    • Chrome:距离视口约1250px时开始加载
    • Firefox:距离视口约1000px时开始加载
  2. 不适合首屏内容:对首屏可见的图片不应使用懒加载,否则会延迟其加载

  3. widthheight属性配合:建议设置明确的尺寸以避免布局偏移(CLS)

    <img src="image.jpg" loading="lazy" width="600" height="400" alt="示例">
    
  4. 与响应式图片的配合

    html

    <img src="small.jpg" 
         srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w" 
         sizes="(max-width: 600px) 500px, (max-width: 1200px) 1000px, 1500px"
         loading="lazy"
         alt="响应式图片示例">
    
  5. iframe也支持loading="lazy" 也可用于 <iframe> 元素

替代值

  • loading="auto":由浏览器决定是否懒加载(默认行为)
  • loading="eager":立即加载(传统方式)

JavaScript API

可以通过 Intersection Observer API 实现类似功能,但原生 loading="lazy" 更简单高效。

最佳实践

  1. 对首屏内容使用 loading="eager" 或省略该属性
  2. 对首屏下方内容使用 loading="lazy"
  3. 为所有图片设置明确的 width 和 height 属性
  4. 考虑使用 <picture> 元素结合懒加载进行响应式设计

示例

html

<!-- 首屏图片 - 立即加载 -->
<img src="hero.jpg" loading="eager" width="1200" height="800" alt="首图">

<!-- 下方内容图片 - 懒加载 -->
<img src="content1.jpg" loading="lazy" width="600" height="400" alt="内容1">
<img src="content2.jpg" loading="lazy" width="600" height="400" alt="内容2">

通过合理使用 loading="lazy",可以显著提升网页性能,特别是在包含大量图片的长页面上。

使用 <picture> 元素结合 loading="lazy" 实现响应式懒加载

将 <picture> 元素与懒加载结合是实现高性能响应式图片的最佳实践之一。下面详细介绍如何实现:

基本结构

html

<picture>
  <source media="(min-width: 1200px)" srcset="large.jpg" loading="lazy">
  <source media="(min-width: 768px)" srcset="medium.jpg" loading="lazy">
  <img src="small.jpg" alt="响应式图片" loading="lazy" width="800" height="600">
</picture>

完整实现方案

1. 标准响应式图片 + 懒加载

html

<picture>
  <!-- 根据屏幕密度提供不同分辨率 -->
  <source 
    type="image/webp" 
    srcset="image-sm.webp 480w,
            image-md.webp 768w,
            image-lg.webp 1200w"
    sizes="(max-width: 600px) 480px,
           (max-width: 1200px) 768px,
           1200px"
    loading="lazy">
  
  <!-- 回退方案 -->
  <source 
    type="image/jpeg" 
    srcset="image-sm.jpg 480w,
            image-md.jpg 768w,
            image-lg.jpg 1200w"
    sizes="(max-width: 600px) 480px,
           (max-width: 1200px) 768px,
           1200px"
    loading="lazy">
  
  <img 
    src="image-sm.jpg" 
    alt="响应式图片示例" 
    loading="lazy"
    width="1200" 
    height="800">
</picture>

2. 艺术指导(Art Direction) + 懒加载

html

<picture>
  <!-- 大屏幕显示宽幅裁剪版本 -->
  <source 
    media="(min-width: 1200px)" 
    srcset="wide-large.jpg 1920w,
            wide-medium.jpg 1200w"
    sizes="100vw"
    loading="lazy">
  
  <!-- 中等屏幕 -->
  <source 
    media="(min-width: 768px)" 
    srcset="square-large.jpg 1200w,
            square-medium.jpg 768w"
    sizes="100vw"
    loading="lazy">
  
  <!-- 移动端显示竖版裁剪 -->
  <img 
    src="portrait-mobile.jpg" 
    srcset="portrait-mobile.jpg 480w,
            portrait-tablet.jpg 768w"
    sizes="100vw"
    alt="艺术指导图片示例"
    loading="lazy"
    width="768" 
    height="1024">
</picture>

关键注意事项

  1. <img> 是必须的

    • <picture> 内必须包含一个 <img> 作为回退
    • 所有懒加载属性应同时加在 <source> 和 <img> 上
  2. 尺寸定义很重要

    html

    <!-- 明确尺寸防止布局偏移 -->
    <img ... width="800" height="600">
    
  3. 现代格式优先

    html

    <picture>
      <source type="image/avif" srcset="image.avif" loading="lazy">
      <source type="image/webp" srcset="image.webp" loading="lazy">
      <img src="image.jpg" loading="lazy" alt="">
    </picture>
    
  4. 与JavaScript配合

    javascript

    // 动态加载图片时
    function loadLazyPicture(element) {
      const picture = element.querySelector('picture');
      const sources = picture.querySelectorAll('source');
      
      sources.forEach(source => {
        source.srcset = source.dataset.srcset;
      });
      
      const img = picture.querySelector('img');
      img.src = img.dataset.src;
    }
    

性能优化技巧

  1. 预加载关键图片

    html

    <link rel="preload" href="hero.jpg" as="image" imagesrcset="hero-sm.jpg 480w, hero-lg.jpg 1200w" imagesizes="100vw">
    
  2. 使用低质量占位图(LQIP)

    html

    <picture>
      <source type="image/webp" srcset="placeholder.webp" data-srcset="real-image.webp" loading="lazy">
      <img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy" alt="">
    </picture>
    
  3. CSS优化

    css

    picture {
      display: block; /* 避免行内元素间隙 */
      overflow: hidden;
    }
    

这种组合方案可以同时获得:

  • 响应式图片适配不同设备
  • 现代图像格式支持
  • 懒加载性能优化
  • 艺术指导能力
  • 带宽节省

各浏览器会根据设备特性自动选择最合适的资源加载,而懒加载确保只有可见区域附近的图片才会实际下载。