Is there any way to render a default image in an HTML <img>
tag, in case the src
attribute is invalid (using only HTML)? If not, what would be your lightweight way to work around it?

- 57,901
- 40
- 134
- 167

- 11,063
- 16
- 55
- 67
-
3HTML has no fallback for broken images. You'd need to use JavaScript to find broken images and change their src attribute. – Blixt Jun 11 '09 at 12:45
-
3@Blixt - What if your client is MS Outlook or someother EMAIL reader and you don't have Javascript, and the object option does not work ... I presume the only solution is alt/text – Xofo Jul 15 '15 at 22:19
-
Actually, Firefox has a *real fallback* for images that don’t load! It places the alternative Text of the image instead of the image, and even applies styling to it! I always liked this way as it took the _alternative text_ seriously. – Andy Jul 13 '22 at 11:39
-
Just a note about alt text: https://www.sitelint.com/blog/best-practices-for-writing-good-alt-text/ – Cezary Tomczyk Apr 09 '23 at 23:08
27 Answers
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.

- 10,259
- 10
- 67
- 98

- 57,901
- 40
- 134
- 167
-
3It worked for me in IE8 after I put in the DTD for HTML 4.01. – Patrick McElhaney Jun 11 '09 at 13:20
-
2This doesn't work if the non-existing image has `X-Frame-Options` set to `SAMEORIGIN` or a more permissive setting. – Attila O. May 09 '13 at 12:50
-
1It works but if the link in object.data is not trusted, it can load all kind of stuff... – Michael_Scharf Oct 26 '13 at 18:30
-
What I did was use a combination of these solutions. It turns out 1 solution is not enough because of various browser clients. This DOES point to perhaps the need for a HTML standard (update) to resolve this type of thing. What I do is use a an alt/text styled with inline CSS for big characters AND javascript AND a background image. The javascript works on Chrome but does not work on Outlook. The alt/text with a background image shows up on Outlook. < – Xofo Jul 16 '15 at 22:52
-
3
-
2@Matheus Sure it can. In HTML4 object can contain flow content (almost everything, including img), and in HTML5 it's transparent, meaning it can contain any valid HTML5. – Patrick McElhaney Jan 14 '17 at 23:29
-
1This really slows down my site when I use it with 10+ images that are not existing. Looks like it crashes the php session. – ssten Jul 16 '19 at 20:08
-
onerror="this.src='error.jpg';this.onerror=null;" this might help – rahim.nagori Jul 06 '20 at 09:08
-
-
It worked for me , onerror="this.src='error.jpg';this.onerror=null; this one is not working – Geethu Jose Nov 10 '22 at 10:57
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 { ...
-
1Using the onerror event to catch broken images is as old as ... well, it's an old technique, and as far as I know, supported in all browsers. – Svend Jun 11 '09 at 18:41
-
4In my opinion. This is the better answer. Here's quirksmodes take on onerror.....seems pretty safe to me. http://www.quirksmode.org/dom/events/error.html#t01 – n0nag0n Jan 10 '13 at 21:08
-
14BTW, if error.jpg does not exist, this causes an infinite loop because it keeps trying to find the image, then onError is called again, it cannot find it, and the whole thing starts again. – borq Mar 01 '13 at 15:35
-
@borq - true for all browsers except latest version on Chrome (v28). It only fires onerror once there. Have to set src to null first in Chrome, then set the image to get it to fire repeatedly. – johntrepreneur Jul 21 '13 at 23:16
-
32
-
23Alternatively, you can write: `onerror="this.src='error.jpg';this.onerror='';"` – Denilson Sá Maia Mar 06 '15 at 00:34
-
6demo is not working in chrome, i can still see the error image – That Realty Programmer Guy Nov 01 '17 at 23:23
-
2The CSS only solution does only work with an empty `alt` attribute on the image tag. At least on my version of Firefox. Please change `
` to `
`. – JojOatXGME Feb 15 '18 at 10:55
-
3When I load this fiddle in Chrome I see the broken image icon partially overlapped by the error-image. Unless this is a mistake on my part I would not consider that a solution. – Koenigsberg Feb 27 '18 at 11:07
-
1I found that @DenilsonSáMaia solution works best, CSS one doesnt render in firefox, and jacquarg javascript solution still caused an infinite loop. – aorticDefiance Oct 10 '18 at 10:40
-
3Worked for me after adding an alt with a whitespace character `alt=" "`. – solarc Sep 10 '19 at 20:48
-
3
-
1it loads two images (in Chrome) if the first image is not broken, which is redundant – bapho Oct 24 '22 at 15:24
-
1No Safari support (still) for the CSS solution: [test](https://jsfiddle.net/qsnpew30/show). – V. Rubinetti Feb 21 '23 at 17:51
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

- 15,447
- 5
- 79
- 98

- 3,321
- 1
- 15
- 14
-
3
-
2
-
To avoid the infinite loop, you can do `onerror="this.onerror=null;this.src='../resources/images/none.jpg'"` – Mike May 04 '23 at 20:21
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>

- 858
- 8
- 13
-
2this one is great! be aware of missing browser support https://caniuse.com/#feat=picture. consider using a polyfill or another solution if you need to support older browsers like IE11. – Hinrich Jul 16 '19 at 16:00
-
1
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.

- 4,412
- 4
- 34
- 51
-
3onError is deprecated as per developer.mozilla.org/en-US/docs/Web/HTML/Element/img – comiventor Mar 16 '20 at 04:57
-
1onerror still seems to be supported https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#image_loading_errors – kevgathuku May 05 '22 at 05:02
-
3the funny thing is nobody knows why its deprecated https://github.com/mdn/sprints/issues/4014 – fin Jul 14 '22 at 22:54
<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.
-
38Doesn't most browsers show a 'broken link' image when the image is not found... In that case, setting the background would not solve the problem. – Justin D. Jul 23 '13 at 19:18
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

- 31,965
- 17
- 72
- 98
<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

- 4,023
- 3
- 19
- 20

- 475
- 4
- 11
-
https://developer.mozilla.org/en/docs/Web/CSS/CSS_Background_and_Borders/Using_CSS_multiple_backgrounds – Emiliano Barboza Aug 04 '16 at 17:01
-
3This only works if image1 is completely opaque. If it has transparency, like most icon images do, then image2 will show through. – jdunning Jul 29 '17 at 01:33
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.

- 680
- 6
- 16
angular2:
<img src="{{foo.url}}" onerror="this.src='path/to/altimg.png'">

- 1,310
- 1
- 18
- 29
-
2While this may work I don't think that it adds any new information. The onerror portion is just vanilla JavaScript and the src binding should already be known by Angular users – Chic May 08 '17 at 17:14
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

- 3,933
- 6
- 40
- 60
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">

- 746
- 4
- 25
-
1onError is deprecated as per https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img – comiventor Mar 16 '20 at 04:56
-
Re being deprecated, not sure why it's marked that way. More here https://stackoverflow.com/a/59366589/28099 – ewbi Nov 21 '20 at 03:22
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="..." />

- 8,025
- 3
- 44
- 57
React
<img
src="https://example.com/does_not_exist.png"
onError={(e) => {
e.currentTarget.src = "https://example.com/default.png"
}}
/>

- 61
- 1
- 2
-
1As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 25 '22 at 08:51
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
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';" />
-
3When using this code, I see `Uncaught TypeError: this.attribute is not a function` in Chrome 43. – John Washam Jul 01 '15 at 15:08
-
onError is deprecated as per developer.mozilla.org/en-US/docs/Web/HTML/Element/img – comiventor Mar 16 '20 at 04:58
-
Re being deprecated, not sure why it's marked that way. More here https://stackoverflow.com/a/59366589/28099 – ewbi Nov 21 '20 at 03:21
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';">

- 412
- 4
- 14
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);
});
}
};
}])

- 6,750
- 4
- 39
- 56
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

- 1,500
- 2
- 21
- 28
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">

- 443
- 4
- 6
I am adding loading="lazy"
to <img>
tag. In some cases it works.

- 15,447
- 5
- 79
- 98

- 101
- 3
here is a simple Jquery that worked for me
$(image).on('error', function(event) {
imgage.attr('src', 'your_image.png');})

- 1
- 2
Some CMS use Markdown to store Website content. It is also possible to define a fallback image in Markdown, just use the alt attribute:

This generates the following HTML output:
<img src="image-notloading.jpg" alt="fallback-image.jpg">
You need a little javascript to make the fallback mechanism work:
<script>
document.querySelectorAll("img").forEach(function(el){
el.setAttribute("onerror","this.src=this.alt;this.onerror='';");
});
</script>

- 1,070
- 10
- 8
HTML Part:
<img [ngStyle]="{'width.px': size}" src="assets/svg/{{code}}.svg"
(error)="handleFlagError($event)">
JS Part:
function handleFlagError($event) {
$event.target.src = 'assets/svg/base.svg';
}

- 1
- 2
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()
.

- 87,323
- 22
- 191
- 272
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");
}
});

- 5,956
- 10
- 39
- 40
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');
}

- 27
- 4