iOS浏览器中picture元素始终加载fallback图的技术问题
iOS端Chrome/Safari下picture标签同时加载WebP与JPEG的问题解决
问题复现
使用<picture>标签实现WebP优先加载、JPEG降级的逻辑,桌面端及安卓浏览器均正常(仅加载对应格式图片),但iOS的Chrome和Safari(即使已支持WebP)会同时发起WebP和JPEG的请求,且原本应懒加载的JPEG会被一次性全部加载(首屏仅3张图的情况下,10张JPEG全部请求,WebP仅加载首屏3张)。
当前代码:
<picture> <source srcSet="image.webp" type="image/webp" /> <img src="original-image.jpg" alt="image" /> </picture>
原因分析
iOS上的Chrome基于WebKit内核(苹果强制要求),WebKit存在一个特殊行为:即使浏览器支持WebP并选中了<source>标签,仍会预加载<img>标签的src属性值。如果同时开启了懒加载,这个预加载逻辑会绕过懒加载判断,直接加载所有JPEG资源。
解决方案
方案1:延迟设置JPEG的src属性
通过JavaScript检测WebP支持性,仅在浏览器不支持WebP时才赋值JPEG地址给img的src,避免不必要的预加载:
<picture> <source srcSet="image.webp" type="image/webp" /> <img data-src="original-image.jpg" alt="image" loading="lazy" /> </picture> <script> // 检测WebP支持 function supportsWebP() { return new Promise((resolve) => { const img = new Image(); img.onload = () => resolve(img.width === 1); img.onerror = () => resolve(false); img.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA'; }); } // 初始化图片 async function initImages() { const supportsWebPFlag = await supportsWebP(); if (!supportsWebPFlag) { document.querySelectorAll('img[data-src]').forEach(img => { img.src = img.dataset.src; }); } } // 页面加载完成后执行 document.addEventListener('DOMContentLoaded', initImages); </script>
方案2:原生picture配置+强制懒加载
确保<img>标签的loading="lazy"属性正确生效,同时给<picture>标签添加loading="lazy"(部分浏览器支持),并将img的src改为srcset:
<picture loading="lazy"> <source srcset="image.webp" type="image/webp" /> <img srcset="original-image.jpg" alt="image" loading="lazy" /> </picture>
注:该方案依赖iOS 15.4+的原生懒加载支持,低版本iOS可能仍存在问题,建议结合方案1使用。
验证方法
使用LambdaTest等工具模拟iOS环境,查看网络请求:
- 支持WebP的iOS浏览器应仅加载WebP资源
- 懒加载的图片仅在进入视口时发起请求
内容的提问来源于stack exchange,提问作者pa_dev_2837
相关产品推荐
相关产品推荐

