如何在picture标签中实现source加载失败时显示默认图片?
解决picture标签所有source加载失败时img默认图不显示的问题
问题原因
浏览器处理<picture>标签时,会优先匹配符合当前媒体查询的<source>资源并尝试加载。如果所有匹配的<source>都加载失败,浏览器不会自动回退加载<img>的默认src,只会显示alt文本,这是浏览器的默认行为逻辑。
修复方法
方法1:监听<source>的错误事件,手动触发<img>加载
给每个<source>添加onerror事件,统计失败的资源数量,当所有<source>都加载失败时,强制让<img>重新加载自身的src。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <picture> <source media="(min-width:650px)" srcset="invalid.jpg" onerror="handleSourceError(this)"> <source media="(min-width:465px)" srcset="invalid.jpg" onerror="handleSourceError(this)"> <img id="fallbackImg" src="https://images.pexels.com/photos/9754/mountains-clouds-forest-fog.jpg" alt="test"> </picture> <script> let failedCount = 0; const totalSources = document.querySelectorAll('picture source').length; const fallbackImg = document.getElementById('fallbackImg'); function handleSourceError() { failedCount++; if (failedCount === totalSources) { // 重新赋值src触发浏览器加载默认图 fallbackImg.src = fallbackImg.src; } } </script> </body> </html>
方法2:用CSS背景图做兜底
放弃<picture>标签,改用<div>配合CSS媒体查询设置背景图,利用CSS背景图的叠加特性,将兜底图作为备选:
<div class="responsive-img" role="img" aria-label="test"></div> <style> .responsive-img { width: 100%; height: 300px; /* 设置固定高度或用padding-top维持比例 */ background: url('https://images.pexels.com/photos/9754/mountains-clouds-forest-fog.jpg') center/cover no-repeat; } @media (min-width: 465px) { .responsive-img { background: url('invalid.jpg') center/cover no-repeat, url('https://images.pexels.com/photos/9754/mountains-clouds-forest-fog.jpg') center/cover no-repeat; } } @media (min-width: 650px) { .responsive-img { background: url('invalid.jpg') center/cover no-repeat, url('https://images.pexels.com/photos/9754/mountains-clouds-forest-fog.jpg') center/cover no-repeat; } } </style>
当高优先级的背景图加载失败时,低优先级的兜底图会自动显示。
方法3:JS动态加载图片
通过JavaScript检测屏幕尺寸,主动加载对应图片,加载失败时直接切换到兜底图:
<img id="responsiveImg" src="https://images.pexels.com/photos/9754/mountains-clouds-forest-fog.jpg" alt="test"> <script> const fallbackSrc = 'https://images.pexels.com/photos/9754/mountains-clouds-forest-fog.jpg'; function loadTargetImg() { let targetSrc = fallbackSrc; if (window.innerWidth >= 650) { targetSrc = 'invalid.jpg'; } else if (window.innerWidth >= 465) { targetSrc = 'invalid.jpg'; } const tempImg = new Image(); tempImg.src = targetSrc; tempImg.onload = () => { document.getElementById('responsiveImg').src = targetSrc; }; tempImg.onerror = () => { document.getElementById('responsiveImg').src = fallbackSrc; }; } // 初始化加载 loadTargetImg(); // 窗口 resize 时重新加载 window.addEventListener('resize', loadTargetImg); </script>
内容的提问来源于stack exchange,提问作者Alex Varela
相关产品推荐
相关产品推荐

