In the past, I posted an answer in SO about how to replace broken images. And the code isjavascript
window.addEventListener( 'error', windowErrorCb, { capture: true }, true ) function windowErrorCb(event) { let target = event.target let isImg = target.tagName.toLowerCase() === 'img' if (isImg) { imgErrorCb() return } function imgErrorCb() { let isImgErrorHandled = target.hasAttribute('data-src-error') if (!isImgErrorHandled) { target.setAttribute('data-src-error', 'handled') target.src = 'backup.png' } else { //anything you want to do console.log(target.alt, 'both origin and backup image fail to load!') } } }
And the point is :css
img error->backup.png->error->backup.png->error->,,,,,
I thought the answer is almost perfect. But it turns out there is more scenes I don't know.html
Until Chrome 70.0.3538.102 in win7, code below wouldn't trigger error event.java
<img />
But code below would trigger!jquery
<img src="" /> <img src />
That does make sense. However, img
without src
wouldn't hidden. They would have 1px border like:git
In this case, we may have to do something about that. For instance,github
img:not([src]) { opacity: 0; }
or a default backgroundImage
which will work on img
though 1px border is still there.app
img:not([src]) { background: no-repeat left top / cover; background-image: linear-gradient(to right, lightblue, pink); /*or your logo*/ }
I still can't find a perfect solution for backgroundImage
. The best answer in SO is like:dom
.app__bg_img_box { background: no-repeat left top / cover; background-image: url(./images/github.png), linear-gradient(to right, lightblue, pink); /* you can also use default.png like code below */ /* background-image: url(./images/github.png), url(./images/default.png); */ }
And the cons is obvious.oop
Another way I figured out is like code below. Here is the simplest code:
let backgroundDivs = Array.from(document.querySelectorAll('.app__bg_img_box')) backgroundDivs.forEach(div => { let imgUrl = window .getComputedStyle(div) .backgroundImage.match(/url\(["']?(.*)["']?\)/) if (imgUrl) { let img = new Image() img.src = imgUrl[1] img.onerror = function(event) { div.style.backgroundImage = 'url(./images/default.png)' img.onerror = null } } })
It will work well in most simple scenes but the cons is also obvious:
If lucky enough, we may have the new API in Images which would make code below work.
background: image('target.gif', 'fallback.gif');