¿Introducir una imagen predeterminada en caso de que el atributo src de un html no sea válido?


¿Hay alguna forma de representar una imagen predeterminada en una etiqueta HTML <img>, en caso de que el atributo src no sea válido (utilizando solo HTML)? Si no, ¿cuál sería su forma ligera de trabajar alrededor de él?

 192
Author: Patrick McElhaney, 2009-06-11

19 answers

Usted pidió 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://appharbor.com/assets/images/stackoverflow-logo.png" alt="example">
    </object>
  </p>

</body>

</html>

Dado que la primera imagen no existe, se mostrará el respaldo (el logotipo de Desbordamiento de pila). Y si está utilizando un realmente navegador antiguo que no es compatible object, simplemente ignorará esa etiqueta y usará la etiqueta img. Ver caniuse sitio web para la compatibilidad. A partir de 2018 este elemento es ampliamente compatible con todos y cada uno de los navegadores de ie6+.

 236
Author: Patrick McElhaney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 17:33:15

Esto funciona bien para mí. 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: CSS solución única Recientemente vi Vitaly Friedman demo una gran solución CSS que no era consciente de. La idea es aplicar la propiedad content a la imagen rota. Normalmente :after o :before no se aplican a las imágenes, pero cuando se rompen, se aplican.

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

Demo: 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 ningún JS ni gobs de CSS. Si necesita aplicar diferentes imágenes en diferentes ubicaciones, simplemente diferencie con una clase: .my-special-case img:before { ...

 244
Author: Svend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-05 19:20:28

Encontró esta solución en Primavera en Acción 3a Ed.

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

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

 44
Author: amit bakle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-19 14:24:51
<style type="text/css">
img {
   background-image: url('/images/default.png')
}
</style>

Asegúrese de introducir las dimensiones de la imagen y si desea que la imagen se tesele o no.

 14
Author: lambacck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-30 15:02:27

No creo que sea posible usar solo HTML. Sin embargo, usando javascript esto debería ser factible. Bassicly loop sobre cada imagen, prueba si está completa y si es naturalWidth 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;
        }
    }
}

Úsalo así:

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

Probado en Chrome y Firefox

 12
Author: Pim Jager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-11 13:07:02

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 item tiene una propiedad url que podría ser null, cuando lo sea, la imagen aparecerá como rota. Esto desencadena la ejecución de la expresión de atributo onerror, como se describió anteriormente. Necesita anular el atributo src como se describió anteriormente, pero necesitará jQuery para acceder a su altSrc. No pude hacer que funcionara con vanilla JavaScript.

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

 9
Author: Obie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-06 01:01:00

<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á desde algún lugar (navegador haciendo una solicitud) image2 es una imagen local predeterminada que se muestra mientras se carga image1. Si image1 devuelve cualquier tipo de error, el usuario no verá ningún cambio y esto estará limpio para la experiencia del usuario

 8
Author: Emiliano Barboza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-02 20:58:24

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

Podemos usar con éxito background-image para vincular la imagen que aparece si falta la imagen dada. Entonces el único problema es la imagen de icono roto - podemos eliminarlo insertando un carácter vacío muy grande, empujando así el contenido fuera de la pantalla de 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 CSS (solo Webkit)

img:before {
  content: " ";
  background-image: url("http://placehold.it/200x200");
  display: block;
  width: 200px;
  height: 200px;
  position: relative;
  z-index: 0;
}
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

O, en jsfiddle: https://jsfiddle.net/xehndm3u/9/

 4
Author: eithed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-27 09:52:53

No hay manera de estar seguro de la gran cantidad de clientes (navegadores) que intentarán ver su página. Un aspecto a considerar es que los clientes de correo electrónico son navegadores web de facto y no pueden manejar tal trickamajickery ...

Como tal, también debe incluir un alt/text con un ANCHO y ALTO PREDETERMINADOS, como este. Esta es una solución HTML pura.

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

Así que la otra buena respuesta sería ligeramente modificada 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 Me imagino que esto también se aplicaría a eso.

Puede aplicar un estilo adicional al alt/text para que sea MUY GRANDE ...

Así que mi respuesta es usar Javascript con un buen respaldo alt/texto.

También encontré esto interesante: Cómo estilizar el atributo alt de una imagen

 2
Author: Xofo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:10

Angular2:

<img src="{{foo.url}}" onerror="this.src='path/to/altimg.png'">
 2
Author: user3601578,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-07 15:22:59

Un simple img-element no es muy flexible, así que lo combiné con un picture-element. de esta manera no se necesita CSS. cuando se produce un error, todos los srcset se establecen en la versión de reserva. una imagen de enlace roto no aparece. no carga versiones de imagen innecesarias. el elemento picture es compatible con el diseño responsivo y múltiples alternativas para los 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>
 2
Author: bapho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-10 17:55:40

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

this.src y 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';" />
 2
Author: Seb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-11 07:38:47

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 img etiqueta:

<img src="..." data-src-error="..." />
 1
Author: Kevin Robatel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 15:24:50

Si está utilizando Angular 1.x puede incluir una directiva que le permitirá recurrir a cualquier número de imágenes. El atributo fallback admite una sola url, varias URL dentro de un array o una expresión angular utilizando datos de ámbito:

<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 de reserva al módulo angular app:

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);
                });
            }
        };
    }])
 1
Author: Rob Evans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-14 10:24:21

Usando Jquery puedes 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");
    }
});
 0
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-11 12:57:01

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

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

Donde ptImage es una dirección de etiqueta <img> obtenida por document.getElementById().

 0
Author: José Esteves Pereira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-05 08:14:39

Google lanzó esta página a las palabras clave "image fallback html", pero debido a que no de lo anterior me ayudó, y estaba buscando un "soporte de reserva 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]-->

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

 0
Author: iorgu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-17 07:43:09

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

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

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

 0
Author: sunsay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-19 19:23:56

Bueno!! Encontré esta manera conveniente, verifique que el atributo height de image sea 0, luego puede sobrescribir el atributo src con la imagen predeterminada: 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');
  }
 -1
Author: suhail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-07 15:43:21