You asked for an HTML only solution…
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Object Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>
<object data="https://stackoverflow.com/does-not-exist.png" type="image/png">
<img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=e5e58ae7df45" alt="Stack Overflow logo and icons and such">
</object>
</p>
</body>
</html>
Since the first image doesn’t exist, the fallback (the sprites used on this web site*) will display. And if you’re using a really old browser that doesn’t support object
, it will ignore that tag and use the img
tag. See caniuse website for compatibility. This element is widely supported by all browsers from IE6+.
* Unless the URL for the image changed (again), in which case you’ll probably see the alt text.
A.L
9,9099 gold badges62 silver badges96 bronze badges
answered Jun 11, 2009 at 12:55
Patrick McElhaneyPatrick McElhaney
57.1k40 gold badges130 silver badges167 bronze badges
11
This works well for me. Maybe you wanna use JQuery to hook the event.
<img src="foo.jpg" onerror="if (this.src != 'error.jpg') this.src = 'error.jpg';" alt="add alternative text here">
Updated with jacquargs error guard
Updated: CSS only solution
I recently saw Vitaly Friedman demo a great CSS solution I wasn’t aware of. The idea is to apply the content
property to the broken image. Normally :after
or :before
do not apply to images, but when they’re broken, they’re applied.
<img src="nothere.jpg" alt="add alternative text here">
<style>
img:before {
content: ' ';
display: block;
position: absolute;
height: 50px;
width: 50px;
background-image: url(ishere.jpg);
}
</style>
Demo: https://jsfiddle.net/uz2gmh2k/2/
As the fiddle shows, the broken image itself is not removed, but this will probably solve the problem for most cases without any JS nor gobs of CSS. If you need to apply different images in different locations, simply differentiate with a class: .my-special-case img:before { ...
Andy
4,0802 gold badges24 silver badges46 bronze badges
answered Jun 11, 2009 at 13:06
SvendSvend
7,7953 gold badges29 silver badges45 bronze badges
13
Found this solution in Spring in Action 3rd Ed.
<img src="../resources/images/Image1.jpg" onerror="this.src='../resources/images/none.jpg'" />
Update:
This is not an HTML only solution… onerror
is javascript
answered Oct 29, 2012 at 9:35
amit bakleamit bakle
3,3011 gold badge15 silver badges14 bronze badges
2
a simple img-element is not very flexible so i combined it with a picture-element. this way no CSS is needed. when an error occurs, all srcset’s are set to the fallback version. a broken link image is not showing up. it does not load unneeded image versions. the picture-element supports responsive design and multiple fallbacks for types that are not supported by the browser.
<picture>
<source id="s1" srcset="image1_not_supported_by_browser.webp" type="image/webp">
<source id="s2" srcset="image2_broken_link.png" type="image/png">
<img src="image3_fallback.jpg" alt="" onerror="this.onerror=null;document.getElementById('s1').srcset=document.getElementById('s2').srcset=this.src;">
</picture>
answered Mar 10, 2017 at 11:17
baphobapho
8108 silver badges13 bronze badges
2
Simple and neat solution involving some good answers and comment.
<img src="foo.jpg" onerror="this.src='error.jpg';this.onerror='';">
It even solve infinite loop risk.
Worked for me.
answered Mar 20, 2019 at 14:55
manish kumarmanish kumar
4,2563 gold badges34 silver badges50 bronze badges
3
<style type="text/css">
img {
background-image: url('/images/default.png')
}
</style>
Be sure to enter dimensions of image and whether you want the image to tile or not.
sehe
365k47 gold badges440 silver badges616 bronze badges
answered Jun 11, 2009 at 12:51
lambaccklambacck
9,6443 gold badges33 silver badges46 bronze badges
1
I don’t think it is possible using just HTML. However using javascript this should be doable. Bassicly we loop over each image, test if it is complete and if it’s naturalWidth is zero then that means that it not found. Here is the code:
fixBrokenImages = function( url ){
var img = document.getElementsByTagName('img');
var i=0, l=img.length;
for(;i<l;i++){
var t = img[i];
if(t.naturalWidth === 0){
//this image is broken
t.src = url;
}
}
}
Use it like this:
window.onload = function() {
fixBrokenImages('example.com/image.png');
}
Tested in Chrome and Firefox
answered Jun 11, 2009 at 13:07
Pim JagerPim Jager
31.8k16 gold badges72 silver badges98 bronze badges
0
<img style="background-image: url(image1), url(image2);"></img>
Use background image that let you add multiple images.
My case:
image1 is the main image, this will get from some place (browser doing a request)
image2 is a default local image to show while image1 is being loaded.
If image1 returns any kind of error, the user won’t see any change and this will be clean for user experience
Mindastic
3,9532 gold badges19 silver badges20 bronze badges
answered Aug 2, 2016 at 20:48
2
If you’re using Angular/jQuery then this might help…
<img ng-src="{{item.url}}" altSrc="{{item.alt_url}}" onerror="this.src = $(this).attr('altSrc')">
Explanation
Assuming that item
has a property url
that might be null, when it is then the image will show up as broken. That triggers execution of onerror
attribute expression, as described above. You need to override the src
attribute as described above, but you will need jQuery to access your altSrc. Couldn’t get it to work with vanilla JavaScript.
Might seem a little hacky but saved the day on my project.
answered Sep 6, 2014 at 1:01
ObieObie
6806 silver badges16 bronze badges
0
angular2:
<img src="{{foo.url}}" onerror="this.src='path/to/altimg.png'">
answered Mar 7, 2016 at 15:22
user3601578user3601578
1,1331 gold badge16 silver badges28 bronze badges
1
An HTML only solution, where the only requirement is that you know the size of the image that you’re inserting. Will not work for transparent images, as it uses background-image
as a filler.
We can successfully use background-image
to link the image that appears if the given image is missing. Then the only problem is the broken icon image — we can remove it by inserting a very big empty character, thus pushing the content outside the display of img
.
img {
background-image: url("http://placehold.it/200x200");
overflow: hidden;
}
img:before {
content: " ";
font-size: 1000px;
}
This image is missing:
<img src="a.jpg" style="width: 200px; height: 200px"/><br/>
And is displaying the placeholder
An CSS only solution (Webkit only)
img:before {
content: " ";
font-size: 1000px;
background-image: url("http://placehold.it/200x200");
display: block;
width: 200px;
height: 200px;
position: relative;
z-index: 0;
margin-bottom: -16px;
}
This image is there:
<img src="http://placehold.it/100x100"/><br/>
This image is missing:
<img src="a.jpg"/><br/>
And is displaying the placeholder
answered Mar 23, 2016 at 16:23
eithedeithed
3,8275 gold badges40 silver badges60 bronze badges
Update: 2022 (works on chrome still!!)
I recently had to build a fall back system which included any number of fallback images. Here’s how I did it using a simple JavaScript function.
HTML
<img src="some_image.tiff"
onerror="fallBackImg(this);"
data-src-1="some_image.png"
data-src-2="another_image.jpg">
JavaScript
function fallBackImg(elem){
elem.error = null;
let index = elem.dataset.fallIndex || 1;
elem.src = elem.dataset[`src-${index}`];
elem.dataset.fallIndex = ++index;
}
I feel like it’s a pretty lightweight way of handling many fallback images.
If you want «HTML only» then this
<img src="some_image.tiff"
onerror="this.error = null;
let i = this.dataset.i || 1;
this.src = this.dataset[`src-${i}`];
this.dataset.i = ++i;"
data-src-1="some_image.png"
data-src-2="another_image.jpg">
answered Jan 2, 2020 at 21:33
RagerRager
6144 silver badges25 bronze badges
2
A modulable version with JQuery, add this at the end of your file:
<script>
$(function() {
$('img[data-src-error]').error(function() {
var o = $(this);
var errorSrc = o.attr('data-src-error');
if (o.attr('src') != errorSrc) {
o.attr('src', errorSrc);
}
});
});
</script>
and on your img
tag:
<img src="..." data-src-error="..." />
answered Nov 12, 2015 at 15:24
Kevin RobatelKevin Robatel
7,9063 gold badges45 silver badges57 bronze badges
There is no way to be sure the myriad number of clients (browsers) that will try to view your page. One aspect to consider is that email clients are defacto web browsers and may not handle such trickamajickery …
As such you should ALSO include an alt/text with a DEFAULT WIDTH and HEIGHT, like this. This is a pure HTML solution.
alt="NO IMAGE" width="800" height="350"
So the other good answer would be slightly modified as follows:
<img src="foo.jpg" onerror="if (this.src != 'error.jpg') this.src = 'error.jpg';" alt="NO IMAGE" width="800" height="350">
I had issues with the object tag in Chrome, but I would imagine this would apply to that as well.
You can further style the alt/text to be VERY BIG …
So my answer is use Javascript with a nice alt/text fallback.
I also found this interesting: How to style an image’s alt attribute
answered Jul 15, 2015 at 22:38
XofoXofo
1,2563 gold badges17 silver badges31 bronze badges
React
<img
src="https://example.com/does_not_exist.png"
onError={(e) => {
e.currentTarget.src = "https://example.com/default.png"
}}
/>
answered Nov 23, 2022 at 2:17
1
The above solution is incomplete, it missed the attribute src
.
this.src
and this.attribute('src')
are NOT the same, the first one contains the full reference to the image, for example http://my.host/error.jpg
, but the attribute just keeps the original value, error.jpg
Correct solution
<img src="foo.jpg" onerror="if (this.src != 'error.jpg' && this.attribute('src') != 'error.jpg') this.src = 'error.jpg';" />
Hash
4,6575 gold badges20 silver badges39 bronze badges
answered Jan 26, 2015 at 15:36
3
3 solutions for this:
Consider following html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img id="imageId">
<script src="setimage.js"></script>
</body>
</html>
Solution one :
reference this block of JS code inside the body tag of your html as
<script src="setimage.js"></script>
and set the src paths, the first is the one if there is an error, the next is the one you hope works first time
var img = document.getElementById("imageId")
img.onerror = () => {
img.src= "../error.png";
}
img.src= "../correct.webp.png";
Solution two:
this solution is almost the same, instead you will call the method, again at the end of your body within a script tag, but would supply the paths there.
function setImageWithFallback(mainImgPath, secondaryImgPath) {
var img = document.getElementById("imageId")
img.onerror = () => {
img.src= mainImgPath;
}
img.src= secondaryImgPath;
}
Solution three:
if its just a single image, this would be the simplest simply set the onerror at the img tag
<img id="imageId" src="../correct.webp.png"
onerror="if (this.src != '../error.png') this.src = '../error.png';">
answered Aug 13, 2021 at 22:55
robskaarrobskaar
3842 silver badges12 bronze badges
If you are using Angular 1.x you can include a directive that will allow you to fallback to any number of images. The fallback attribute supports a single url, multiple urls inside an array, or an angular expression using scope data:
<img ng-src="myFirstImage.png" fallback="'fallback1.png'" />
<img ng-src="myFirstImage.png" fallback="['fallback1.png', 'fallback2.png']" />
<img ng-src="myFirstImage.png" fallback="myData.arrayOfImagesToFallbackTo" />
Add a new fallback directive to your angular app module:
angular.module('app.services', [])
.directive('fallback', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var errorCount = 0;
// Hook the image element error event
angular.element(element).bind('error', function (err) {
var expressionFunc = $parse(attrs.fallback),
expressionResult,
imageUrl;
expressionResult = expressionFunc(scope);
if (typeof expressionResult === 'string') {
// The expression result is a string, use it as a url
imageUrl = expressionResult;
} else if (typeof expressionResult === 'object' && expressionResult instanceof Array) {
// The expression result is an array, grab an item from the array
// and use that as the image url
imageUrl = expressionResult[errorCount];
}
// Increment the error count so we can keep track
// of how many images we have tried
errorCount++;
angular.element(element).attr('src', imageUrl);
});
}
};
}])
answered Jun 14, 2017 at 10:24
Rob EvansRob Evans
6,7004 gold badges38 silver badges56 bronze badges
0
Using Jquery you could do something like this:
$(document).ready(function() {
if ($("img").attr("src") != null)
{
if ($("img").attr("src").toString() == "")
{
$("img").attr("src", "images/default.jpg");
}
}
else
{
$("img").attr("src", "images/default.jpg");
}
});
answered Jun 11, 2009 at 12:57
JonJon
5,88810 gold badges38 silver badges40 bronze badges
For any image, just use this javascript code:
if (ptImage.naturalWidth == 0)
ptImage.src = '../../../../icons/blank.png';
where ptImage
is a <img>
tag address obtained by document.getElementById()
.
Flexo♦
86.4k22 gold badges189 silver badges271 bronze badges
answered Feb 5, 2012 at 8:10
Google threw out this page to the «image fallback html» keywords, but because non of the above helped me, and I was looking for a «svg fallback support for IE below 9», I kept on searching and this is what I found:
<img src="base-image.svg" alt="picture" />
<!--[if (lte IE 8)|(!IE)]><image src="fallback-image.png" alt="picture" /><![endif]-->
It might be off-topic, but it resolved my own issue and it might help someone else too.
answered Aug 17, 2017 at 7:43
orghuorghu
6847 silver badges25 bronze badges
In addition to Patrick’s brilliant answer, for those of you who are searching for a cross-platform angular js solution, here you go:
<object type="image/png" data-ng-attr-data="{{ url || 'data:' }}">
<!-- any html as a fallback -->
</object>
Here’s a plunk where I was playing trying to find the right solution: http://plnkr.co/edit/nL6FQ6kMK33NJeW8DVDY?p=preview
answered Apr 19, 2018 at 19:23
sunsaysunsay
1,4902 gold badges21 silver badges28 bronze badges
If you have created dynamic Web project and have placed the required image in WebContent then you can access the image by using below mentioned code in Spring MVC:
<img src="Refresh.png" alt="Refresh" height="50" width="50">
You can also create folder named img and place the image inside the folder img and place that img folder inside WebContent then you can access the image by using below mentioned code:
<img src="img/Refresh.png" alt="Refresh" height="50" width="50">
answered Mar 12, 2019 at 17:39
I am adding loading=»lazy» to img tag. In some cases it works..
answered Jan 14, 2022 at 9:57
here is a simple Jquery that worked for me
$(image).on('error', function(event) {
imgage.attr('src', 'your_image.png');})
answered Jan 22, 2022 at 13:50
Well!!
I found this way convenient , check for the height attribute of image to be 0, then you can overwrite the src attribute with default image:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image
image.setAttribute('src','../icons/<some_image>.png');
//check the height attribute.. if image is available then by default it will
//be 100 else 0
if(image.height == 0){
image.setAttribute('src','../icons/default.png');
}
answered Feb 7, 2018 at 11:53
This is actually tricky, especially if you plan on returning an image url for use cases where you need to concatenate strings with the onerror
condition image URL, e.g. you might want to programatically set the url
parameter in CSS.
The trick is that image loading is asynchronous by nature so the onerror
doesn’t happen sunchronously, i.e. if you call returnPhotoURL
it immediately returns undefined
bcs the asynchronous method of loading/handling the image load just began.
So, you really need to wrap your script in a Promise then call it like below. NOTE: my sample script does some other things but shows the general concept:
returnPhotoURL().then(function(value){
doc.getElementById("account-section-image").style.backgroundImage = "url('" + value + "')";
});
function returnPhotoURL(){
return new Promise(function(resolve, reject){
var img = new Image();
//if the user does not have a photoURL let's try and get one from gravatar
if (!firebase.auth().currentUser.photoURL) {
//first we have to see if user han an email
if(firebase.auth().currentUser.email){
//set sign-in-button background image to gravatar url
img.addEventListener('load', function() {
resolve (getGravatar(firebase.auth().currentUser.email, 48));
}, false);
img.addEventListener('error', function() {
resolve ('//rack.pub/media/fallbackImage.png');
}, false);
img.src = getGravatar(firebase.auth().currentUser.email, 48);
} else {
resolve ('//rack.pub/media/fallbackImage.png');
}
} else {
img.addEventListener('load', function() {
resolve (firebase.auth().currentUser.photoURL);
}, false);
img.addEventListener('error', function() {
resolve ('https://rack.pub/media/fallbackImage.png');
}, false);
img.src = firebase.auth().currentUser.photoURL;
}
});
}
Нередко бывает, что при загрузке веб-страницы какие-то изображения оказываются недоступны, и браузер услужливо рисует на их месте пустые контуры. В этой статье я расскажу, как обработать ошибки загрузки изображений и подставить вместо них другое изображение.
Допустим, у нас на сервере лежит файл: https://svgshare.com/i/7ck.svg
Рассмотрим следующий пример. Сколько изображений будет показано?
<html> <head> <meta charset="utf-8" content="text/html; charset=utf-8"/> <style> html, body { height: 100px; width: auto; } </style> </head> <body> <div class="achievement-image"> <img src="https://svgshare.com/i/7ck.svg"> <img src="//svgshare.com/i/7ck.svg"> <img src="svgshare.com/i/7ck.svg"> <img src="7ck.svg"> </div> </body> </html>
Одно, максимум два.
Ответ зависит от того, как открыть этот код. Если разместить его на сервере, вроде https://myserver.com, мы увидим первые два изображения. Если же сохранить его локально и открыть в браузере html файл — только одно. Для ясности я покажу, во что превращаются ссылки из атрибута src в обоих случаях.
В случае сервера https://myserver.com имеем:
https://svgshare.com/i/7ck.svg
https://svgshare.com/i/7ck.svg
https://myserver.com/svgshare.com/i/7ck.svg
https://myserver.com/7ck.svg
В случае локального файла из file:///home/leksa/html/example.html имеем:
https://svgshare.com/i/7ck.svg
file://svgshare.com/i/7ck.svg
file:///home/leksa/html/svgshare.com/i/7ck.svg
file:///home/leksa/html/7ck.svg
Для отслеживания и реакции на успешную или неуспешную загрузку изображения HTML предлагает нам два события, доступных для тега img: onload
и onerror
. Как следует из названия, первое событие возникает, когда изображение было загружено, а второе, когда что-то пошло не так.
Модифицируем наш код и проверим работу этих событий в консоли браузера.
<div class="achievement-image"> <img src="https://svgshare.com/i/7ck.svg" onload="console.log('load 1')" onerror="console.log('error 1')"> <img src="//svgshare.com/i/7ck.svg" onload="console.log('load 2')" onerror="console.log('error 2')"> <img src="svgshare.com/i/7ck.svg" onload="console.log('load 3')" onerror="console.log('error 3')"> <img src="7ck.svg" onload="console.log('load 4')" onerror="console.log('error 4')"> </div>
Как и ожидалось, последние три изображения спровоцировали событие onerror. Назначим на него свой обработчик (потребуется подключить библиотеку JQuery) и подменим атрибут src на адрес желаемого изображения.
$(document).ready(function() { $(".image-container img").each(function(key, item) { $(item).on("error", function() { showDefaultImage(this); }).attr('src', $(item).attr('src')); }); }); function showDefaultImage(img) { $(img).attr('src', 'https://svgshare.com/i/7bo.svg'); $(img).off("error"); }
В интернете есть много примеров решения данной задачи, однако есть один важный момент, о котором часто забывают. Хочу обратить ваше внимание на вызов
$(item).on(...).attr('src', $(item).attr('src'))
после назначения обработчика. Атрибут src устанавливается в то же значение, в котором он изначально был. Зачем это нужно?
Для ответа на этот вопрос вернёмся к последовательности возникновения событий.
- Событие
DOMContentLoaded
возникает, когда построено дерево DOM, а также загружены и выполнены все скрипты. При этом внешние ресурсы, включая изображения и стили, могут быть ещё не загружены. - Событие
load
объекта window возникает, когда страница со всеми ресурсами была загружена. - Событие
ready
специфично для JQuery, согласно документации, оно аналогично событию DOMContentLoaded, то есть не дожидается загрузки мультимедийного контента.
Откроем код, приведённый ниже, и посмотрим на вывод в консоли браузера.
<html> <head> <meta charset="utf-8" content="text/html; charset=utf-8"/> <style> html, body { height: 100px; width: auto; } </style> <script> $(document).on("DOMContentLoaded", function() { console.log("document loaded"); }); $(window).on("load", function() { console.log("content loaded"); }); $(document).ready(function() { console.log(“JQuery ready”); }); </script> </head> <body> <div class="image-container"> <img src="https://svgshare.com/i/7ck.svg" onload="console.log('load 1')" onerror="console.log('error 1')"> <img src="//svgshare.com/i/7ck.svg" onload="console.log('load 2')" onerror="console.log('error 2')"> <img src="svgshare.com/i/7ck.svg" onload="console.log('load 3')" onerror="console.log('error 3')"> <img src="7ck.svg" onload="console.log('load 4')" onerror="console.log('error 4')"> </div> </body> </html>
Тут есть кое-что интересное. Вопреки ожиданием, событие ready срабатывает после загрузки всего контента (включая изображения), аналогично событию load. А значит, на момент создания обработчиков, события error и load уже произошли, и обработчики никогда не будут вызваны.
В браузере firefox картина примерно такая же.
Это вынуждает прибегать к не совсем красивому решению, когда мы заставляем браузер загрузить изображения заново, уже после привязки обработчиков, путём установки атрибута src в то же самое значение.
Окончательный вариант кода приведён ниже (живой пример).
<html> <head> <meta charset="utf-8" content="text/html; charset=utf-8"/> <style> html, body { height: 100px; width: auto; } </style> <script> // $(document).on("DOMContentLoaded", function() { $(document).ready(function() { $(".image-container img").each(function(key, item) { $(item).on("error", function() { showDefaultImage(this); }).attr('src', $(item).attr('src')); }); }); function showDefaultImage(img) { $(img).attr('src', 'https://svgshare.com/i/7bo.svg'); $(img).off("error"); } </script> </head> <body> <div class="image-container"> <img src="https://svgshare.com/i/7ck.svg"> <img src="//svgshare.com/i/7ck.svg"> <img src="svgshare.com/i/7ck.svg"> <img src="7ck.svg"> </div> </body> </html>
The other day I encountered some issues with images for external sources not loading.
I saved a link to someone’s Twitter profile image in this case. When the user changes this image, it doesn’t auto reflect the new one.
So I decided to look into fallback images.
And it’s surprisingly easy.
What we want to achieve:
- Load the image
- If it doesn’t load, show the fallback
Note: Alternatively, you could decide to remove the image
HTML on error fallback images
Let’s set up a sample HTML experiment.
<img
src="https://images.pexels.com/photos/163822/color-umbrella-red-yellow-163822.jpeg"
/>
Enter fullscreen mode
Exit fullscreen mode
This will load an Photo by Pixabay from Pexels (a stock image site).
This will work perfectly, but now let’s try and destroy it by randomly adding some numbers to the image.
<img
src="https://images.pexels.com/photos/163822/color-umbrella-red-yellow-00000.jpeg"
/>
Enter fullscreen mode
Exit fullscreen mode
With this, we get the super annoying broken image.
So what can we do when this happens?
We can use the onerror
attribute on the image to set a fallback.
It works like this:
<img
src="https://images.pexels.com/photos/163822/color-umbrella-red-yellow-00000.jpeg"
onerror="this.onerror=null; this.src='https://images.pexels.com/photos/159868/lost-cat-tree-sign-fun-159868.jpeg'"
/>
Enter fullscreen mode
Exit fullscreen mode
We use the onerror
to set the error to null and set the src of the image to a fallback.
In our case, a photo of a missing cat.
Note: It’s not a great practice to rely on external images. You ideally want to have the fallback image locally in the file system, so it’s a reliable fallback.
You can see it in action in the following CodePen.
The first image loads, and the second one is broken.
Thank you for reading, and let’s connect!
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter
If you develop and push to production, you most likely have experienced broken images on your dev instance. You may have also run into broken images on production due to user/admin error, etc. Wouldn’t it be nice if you could display a default placeholder image without having to take a hit on your file system, checking to see if it exists, before your load each image?
Thanks to Ryan Stille’s recent blog post, I have been made aware of a (not so great) solution. Apparently the img tag, along with others such as object, script and style have error events. We can listen for the error event and load a placeholder image in place of the default browser error image.
The catch is the event handler must be attached before the browser fires the error event. Also, the error event may not be correctly fired when the page is served locally. The error event relies on HTTP status codes and will generally not be triggered if the URL uses the “file:” protocol.
In simpler terms, the only solution I’ve found is to either place the event handler inline with the img tag, assign the img src via JavaScript or recursively search each image’s complete state or naturalWidth once the window is done loading. I’ve tried using “$().on()” and “$(“img”).error()” both after the document loads and inline before the element is loaded. However neither solution works, which doesn’t make much sense to me.
I am including multiple examples because this is not a one-solution-fits-all scenario.
The first working example displays a placeholder image using the inline method if the error event is thrown. Notice the onerror handler is reset when it’s run so you don’t run into an infinite loop if your placeholder image also fails.
<img src="images/myImage.jpg" alt="My Image" onerror="imageError(this)"> <script> function imageError(element) { element.onerror=''; element.src='/images/imgPlaceholder.png'; } </script>
The second working example, also using the inline method, will call a script that will report the broken image and load the placeholder. The script returns an image with the proper image MIME type.
<img src="images/myImage.jpg" alt="My Image" onerror="imageError(this)"> <script> function imageError(element) { element.onerror=''; element.src='logBrokenImage.cfm?image=' + element.src'; } </script>
The third working example uses JavaScript to load the image and displays a placeholder if that image fails to load.
<img id="myImage"> <script> $('img').one( 'error', function() { $(this).attr( 'src', '/images/imgPlaceholder.png' ); }); $('#myImage').attr( 'src', 'myImage.jpg' ); </script>
The final working example recursively searches through each image after the window loads. If it finds the state incomplete or the natural width of the image is 0, then it loads the placeholder image.
<img src="images/myImage.jpg" alt="My Image"> <script> $(window).load(function() { $('img').each(function() { if ( !this.complete || ( !$.browser.msie && ( typeof this.naturalWidth == "undefined" || this.naturalWidth == 0 ) ) ) { this.src = '/images/imgPlaceholder.png'; } }); }); </script>
#error, #event, #handler, #img, #javascript, #jquery, #src