Is there any way to render a default image in an HTML tag, in case the
src
attribute is invalid (using only HTML)? If not, what would
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');
}
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
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.
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="http://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.
<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
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);
});
}
};
}])