¿Ingresando una imagen predeterminada en caso de que el atributo src de un html <img> no sea válido?

268

¿Hay alguna forma de representar una imagen predeterminada en una <img>etiqueta HTML , en caso de que el srcatributo sea inválido (usando solo HTML)? Si no, ¿cuál sería su forma ligera de solucionarlo?

Galilyou
fuente
3
HTML no tiene respaldo para las imágenes rotas. Debería usar JavaScript para encontrar imágenes rotas y cambiar su atributo src.
Blixt
2
@Blixt - ¿Qué sucede si su cliente es MS Outlook o algún otro lector de CORREO ELECTRÓNICO y no tiene Javascript, y la opción de objeto no funciona? Supongo que la única solución es alt / text
Xofo

Respuestas:

319

Solicitaste una solución solo HTML ...

 <!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>

Como la primera imagen no existe, se mostrará el respaldo (los sprites utilizados en este sitio web *). Y si está utilizando un navegador realmente antiguo que no es compatible object, ignorará esa etiqueta y la usará img. Ver el sitio web de caniuse para compatibilidad. Este elemento es ampliamente compatible con todos los navegadores de IE6 +.

* A menos que la URL de la imagen haya cambiado (nuevamente), en cuyo caso probablemente verá el texto alternativo.

Patrick McElhaney
fuente
3
Funcionó para mí en IE8 después de instalar DTD para HTML 4.01.
Patrick McElhaney
Esto no funciona si la imagen no existente se ha X-Frame-Optionsestablecido en SAMEORIGINuna configuración más permisiva.
Atila O.
Funciona, pero si el enlace en object.data no es confiable, puede cargar todo tipo de cosas ...
Michael_Scharf
1
El elemento 'img' no se puede anidar dentro del elemento 'objeto'.
Matheus Miranda
2
@Matheus Claro que sí. En HTML4, el objeto puede contener contenido de flujo (casi todo, incluido img), y en HTML5 es transparente, lo que significa que puede contener cualquier HTML5 válido.
Patrick McElhaney
318

Esto funciona bien para mi. Tal vez quieras usar JQuery para enganchar el evento.

 <img src="foo.jpg" onerror="if (this.src != 'error.jpg') this.src = 'error.jpg';">

Actualizado con jacquargs error guard

Actualizado: solución única de CSS Recientemente vi a Vitaly Friedman demostrar una gran solución de CSS que no conocía. La idea es aplicar la contentpropiedad a la imagen rota. Normalmente :aftero :beforeno se aplican a las imágenes, pero cuando están rotas, se aplican.

<img src="nothere.jpg">
<style>
img:before {
    content: ' ';
    display: block;
    position: absolute;
    height: 50px;
    width: 50px;
    background-image: url(ishere.jpg);
</style>

Demostración: https://jsfiddle.net/uz2gmh2k/2/

Como muestra el violín, la imagen rota en sí no se elimina, pero esto probablemente resolverá el problema en la mayoría de los casos sin JS ni trozos de CSS. Si necesita aplicar diferentes imágenes en diferentes ubicaciones, simplemente diferencie con una clase:.my-special-case img:before { ...

Svend
fuente
3
En mi opinión. Esta es la mejor respuesta. Aquí los modos peculiares toman el error ... me parece bastante seguro. quirksmode.org/dom/events/error.html#t01
n0nag0n
12
Por cierto, si error.jpg no existe, esto causa un bucle infinito porque sigue tratando de encontrar la imagen, luego se llama a onError nuevamente, no puede encontrarlo y todo vuelve a comenzar.
borq
30
Para evitar el riesgo de bucle infinito, simplemente agregue una prueba: <img src = "foo.jpg" onerror = "if (this.src! = 'Error.jog') this.src = 'error.jpg';">
jacquarg
21
Alternativamente, puede escribir:onerror="this.src='error.jpg';this.onerror='';"
Denilson Sá Maia
66
¿Dónde está jQuery en esto?
Praveen Kumar Purushothaman
64

Encontré esta solución en Spring in Action 3rd Ed.

<img src="../resources/images/Image1.jpg" onerror="this.src='../resources/images/none.jpg'" />

Actualización: Esta no es una solución solo HTML ... onerrores javascript

amit bakle
fuente
3
Esto funciona muy bien. Aquí hay una actualización con una imagen alternativa en imgur: <img src = "a-missing-image.jpg" alt = "" onerror = "this.src = 'http: ///i.imgur.com/hfM1J8s.png' ">
arpo
15

<img style="background-image: url(image1), url(image2);"></img>                                            

Use una imagen de fondo que le permita agregar varias imágenes. Mi caso: image1 es la imagen principal, esto se obtendrá de algún lugar (el navegador está haciendo una solicitud) image2 es una imagen local predeterminada para mostrar mientras se carga image1. Si image1 devuelve algún tipo de error, el usuario no verá ningún cambio y esto estará limpio para la experiencia del usuario

Emiliano Barboza
fuente
Esto solo funciona si image1 es completamente opaca. Si tiene transparencia, como la mayoría de las imágenes de iconos, entonces image2 se mostrará.
jdunning
14
<style type="text/css">
img {
   background-image: url('/images/default.png')
}
</style>

Asegúrese de ingresar las dimensiones de la imagen y si desea que la imagen se muestre en mosaico o no.

lambacck
fuente
28
La mayoría de los navegadores no muestran una imagen de 'enlace roto' cuando no se encuentra la imagen ... En ese caso, establecer el fondo no resolvería el problema.
Justin D.
13

No creo que sea posible usando solo HTML. Sin embargo, usar JavaScript debería ser factible. Bassicly hacemos un bucle sobre cada imagen, verificamos si está completa y si es natural El ancho es cero, entonces eso significa que no se encuentra. Aquí está el código:

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;
        }
    }
}

Úselo así:

 window.onload = function() {
    fixBrokenImages('example.com/image.png');
 }

Probado en Chrome y Firefox

Pim Jager
fuente
2
Está funcionando Pim, y es totalmente reutilizable, pero preferiría la opción ligera para este mismo caso. Muchas gracias :) +1
Galilyou
Usted salvó toda mi vida señor.
Beardminator
12

Si está utilizando Angular / jQuery, esto podría ayudar ...

<img ng-src="{{item.url}}" altSrc="{{item.alt_url}}" onerror="this.src = $(this).attr('altSrc')">

Explicación

Suponiendo que itemtiene una propiedad urlque podría ser nula, cuando lo sea, la imagen se mostrará rota. Eso desencadena la ejecución de la onerrorexpresión de atributo, como se describió anteriormente. srcDebe anular el atributo como se describe anteriormente, pero necesitará jQuery para acceder a su altSrc. No se pudo hacer que funcione con JavaScript de vainilla.

Puede parecer un poco hacky pero salvó el día en mi proyecto.

Obie
fuente
11

un elemento img simple no es muy flexible, así que lo combiné con un elemento de imagen. de esta manera no se necesita CSS. cuando se produce un error, todos los srcset se configuran en la versión alternativa. una imagen de enlace rota no se muestra. no carga versiones de imagen innecesarias. el elemento de imagen admite un diseño receptivo y múltiples fallos para tipos que no son compatibles con el navegador.

<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>
bapho
fuente
este es genial! tenga en cuenta que falta el soporte del navegador caniuse.com/#feat=picture . considere usar un polyfill u otra solución si necesita admitir navegadores antiguos como IE11.
Hinrich
7

angular2:

<img src="{{foo.url}}" onerror="this.src='path/to/altimg.png'">
user3601578
fuente
1
Si bien esto puede funcionar, no creo que agregue ninguna información nueva. La parte onerror es solo JavaScript vainilla y los usuarios de Angular ya deberían conocer el enlace src
Chic
7

Solución simple y ordenada que implica algunas buenas respuestas y comentarios.

<img src="foo.jpg" onerror="this.src='error.jpg';this.onerror='';">

Incluso resuelve el riesgo de bucle infinito.

Trabajó para mi.

kumar viril
fuente
En mi opinión, esto definitivamente no se ve elegante.
Script47
1
@ Script47 Está ordenada, repito ordenada
manish kumar
1
No, tampoco diría que está bien. Sin mencionar que esto es probablemente una repetición de otras soluciones.
Script47
¡Funciona de maravilla! ¡Gracias!
Goehybrid
1
Salvador de la vida. No quería elegante, quería simple y de trabajo. ¡Gracias!
Kit
7

Una solución solo HTML, donde el único requisito es que conozca el tamaño de la imagen que está insertando. No funcionará para imágenes transparentes, ya que se utiliza background-imagecomo relleno.

Podemos usar background-imagecon éxito para vincular la imagen que aparece si falta la imagen dada. Entonces, el único problema es la imagen de icono rota: podemos eliminarla insertando un carácter vacío muy grande, empujando así el contenido fuera de la pantalla 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


Una solución solo para CSS (solo Webkit)

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

eithed
fuente
4

No hay forma de estar seguro de la gran cantidad de clientes (navegadores) que intentarán ver su página. Un aspecto a tener en cuenta es que los clientes de correo electrónico son navegadores web de facto y no pueden manejar tales trucos ...

Como tal, TAMBIÉN debe incluir un texto alternativo con un ANCHO y ALTURA POR DEFECTO, como este. Esta es una solución HTML pura.

alt="NO IMAGE" width="800" height="350"

Entonces, la otra buena respuesta se modificaría ligeramente de la siguiente manera:

<img src="foo.jpg" onerror="if (this.src != 'error.jpg') this.src = 'error.jpg';" alt="NO IMAGE" width="800" height="350">

Tuve problemas con la etiqueta de objeto en Chrome, pero imagino que esto también se aplicaría a eso.

Puede diseñar aún más el alt / text para que sea MUY GRANDE ...

Entonces mi respuesta es usar Javascript con una buena alternativa de texto / alt.

También encontré esto interesante: cómo diseñar el atributo alt de una imagen

Xofo
fuente
3

Una versión modulable con JQuery , agregue esto al final de su archivo:

<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>

y en tu imgetiqueta:

<img src="..." data-src-error="..." />
Kevin Robatel
fuente
3

La solución anterior está incompleta , se perdió el atributo src.

this.srcy this.attribute('src')NO son lo mismo, el primero contiene la referencia completa a la imagen, por ejemplo http://my.host/error.jpg, pero el atributo solo mantiene el valor original,error.jpg

Solución correcta

<img src="foo.jpg" onerror="if (this.src != 'error.jpg' && this.attribute('src') != 'error.jpg') this.src = 'error.jpg';" />
Seb
fuente
3
Cuando uso este código, veo Uncaught TypeError: this.attribute is not a functionen Chrome 43.
John Washam
¿Estás usando jQuery?
mix3d
onError está en desuso según developer.mozilla.org/en-US/docs/Web/HTML/Element/img
comiventor
2

Si está utilizando Angular 1.x, puede incluir una directiva que le permitirá recurrir a cualquier cantidad de imágenes. El atributo de respaldo admite una única url, múltiples urls dentro de una matriz o una expresión angular utilizando datos de alcance:

<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" />

Agregue una nueva directiva alternativa a su módulo de aplicación angular:

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);
                });
            }
        };
    }])
Rob Evans
fuente
¡Buena idea! Un conjunto de imágenes de
respaldo
1

Recientemente tuve que construir un sistema alternativo que incluyera cualquier cantidad de imágenes alternativas. Así es como lo hice usando una simple función de JavaScript.

HTML

<img src="some_image.tiff"
    onerror="fallBackImg(this);"
    data-fallIndex="1"
    data-fallback1="some_image.png"
    data-fallback2="some_image.jpg">

JavaScript

function fallBackImg(elem){
    elem.onerror = null;
    let index = +elem.dataset.fallIndex;
    elem.src = elem.dataset[`fallback${index}`];
    index++;
    elem.dataset.fallbackindex = index;
}

Siento que es una forma bastante ligera de manejar muchas imágenes de respaldo.

Rager
fuente
onError está en desuso según developer.mozilla.org/en-US/docs/Web/HTML/Element/img
comiventor
0

Usando Jquery podrías hacer algo como esto:

$(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");
    }
});
Jon
fuente
0

Para cualquier imagen, solo use este código javascript:

if (ptImage.naturalWidth == 0)
    ptImage.src = '../../../../icons/blank.png';

donde ptImagees una <img>dirección de etiqueta obtenida por document.getElementById().

José Esteves Pereira
fuente
0

Google lanzó esta página a las palabras clave "Image Fallback html", pero debido a que nada de lo anterior me ayudó, y estaba buscando un "soporte de respaldo svg para IE por debajo de 9", seguí buscando y esto es lo que encontré:

<img src="base-image.svg" alt="picture" />
<!--[if (lte IE 8)|(!IE)]><image src="fallback-image.png" alt="picture" /><![endif]-->

Puede estar fuera de tema, pero resolvió mi propio problema y podría ayudar a alguien más también.

Sándor Zuboly
fuente
0

Además de la brillante respuesta de Patrick , para aquellos de ustedes que buscan una solución angular js multiplataforma, aquí están:

<object type="image/png" data-ng-attr-data="{{ url || 'data:' }}">
    <!-- any html as a fallback -->
</object>

Aquí hay un momento en el que estaba jugando tratando de encontrar la solución correcta: http://plnkr.co/edit/nL6FQ6kMK33NJeW8DVDY?p=preview

sunsay
fuente
0

Si ha creado un proyecto web dinámico y ha colocado la imagen requerida en WebContent, puede acceder a la imagen utilizando el código mencionado a continuación en Spring MVC:

<img src="Refresh.png" alt="Refresh" height="50" width="50">

También puede crear una carpeta llamada img y colocar la imagen dentro de la carpeta img y colocar esa carpeta img dentro de WebContent, luego puede acceder a la imagen utilizando el código mencionado a continuación:

<img src="img/Refresh.png" alt="Refresh" height="50" width="50">
Yoshita Mahajan
fuente
-2

¡¡Bien!! Encontré esta manera conveniente, verifique que el atributo de altura de la imagen sea 0, luego puede sobrescribir el atributo src con la imagen predeterminada: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/ Imagen

 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');
  }
suhail
fuente