Immissione di un'immagine predefinita nel caso in cui l'attributo src di un html <img> non sia valido?


268

Esiste un modo per eseguire il rendering di un'immagine predefinita in un <img>tag HTML , nel caso in cui l' srcattributo non sia valido (utilizzando solo HTML)? In caso contrario, quale sarebbe il tuo modo leggero per aggirarlo?


3
HTML non ha fallback per immagini rotte. Dovresti usare JavaScript per trovare immagini rotte e modificare il loro attributo src.
Blixt,

2
@Blixt - Cosa succede se il tuo client è MS Outlook o un altro lettore EMAIL e non hai Javascript, e l'opzione oggetto non funziona ... Presumo che l'unica soluzione sia alt / text
Xofo

Risposte:


319

Hai chiesto una soluzione 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>

Poiché la prima immagine non esiste, verrà visualizzato il fallback (gli sprite utilizzati in questo sito Web *). E se stai usando un browser molto vecchio che non supporta object, ignorerà quel tag e userà il imgtag. Vedere il sito Web caniuse per la compatibilità. Questo elemento è ampiamente supportato da tutti i browser di IE6 +.

* A meno che l'URL per l'immagine non sia cambiato (di nuovo), nel qual caso probabilmente vedrai il testo alternativo.


3
Ha funzionato per me in IE8 dopo aver inserito il DTD per HTML 4.01.
Patrick McElhaney,

Questo non funziona se l'immagine inesistente è stata X-Frame-Optionsimpostata su SAMEORIGINo su un'impostazione più permissiva.
Attila O.

Funziona ma se il collegamento in object.data non è affidabile, può caricare qualsiasi tipo di roba ...
Michael_Scharf,

1
L'elemento 'img' non può essere nidificato all'interno dell'elemento 'oggetto'.
Matheus Miranda,

2
@Matheus Certo che può. In HTML4 l'oggetto può contenere contenuto di flusso (quasi tutto, incluso img) e in HTML5 è trasparente, il che significa che può contenere qualsiasi HTML5 valido.
Patrick McElhaney,

318

Questo funziona bene per me. Forse vuoi usare JQuery per agganciare l'evento.

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

Aggiornato con la protezione dagli errori di jacquargs

Aggiornato: unica soluzione CSS Di recente ho visto la demo di Vitaly Friedman un'ottima soluzione CSS di cui non ero a conoscenza. L'idea è di applicare la contentproprietà all'immagine rotta. Normalmente :aftero :beforenon si applicano alle immagini, ma quando sono rotte, vengono applicate.

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

Come mostra il violino, l'immagine rotta stessa non viene rimossa, ma questo probabilmente risolverà il problema per la maggior parte dei casi senza JS né gobbe di CSS. Se è necessario applicare immagini diverse in posizioni diverse, è sufficiente differenziarsi con una classe:.my-special-case img:before { ...


3
Secondo me. Questa è la risposta migliore Ecco quirksmodes assumere onerror ..... mi sembra abbastanza sicuro. quirksmode.org/dom/events/error.html#t01
n0nag0n

12
A proposito, se error.jpg non esiste, questo provoca un ciclo infinito perché continua a provare a trovare l'immagine, quindi onError viene chiamato di nuovo, non riesce a trovarlo e tutto ricomincia.
Borq

30
Per evitare il rischio di loop infinito, basta aggiungere un test: <img src = "foo.jpg" onerror = "if (this.src! = 'Error.jog') this.src = 'error.jpg';">
jacquarg

21
In alternativa, puoi scrivere:onerror="this.src='error.jpg';this.onerror='';"
Denilson Sá Maia il

6
Dov'è jQuery in questo?
Praveen Kumar Purushothaman,

64

Ho trovato questa soluzione in Spring in Action 3rd Ed.

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

Aggiornamento: questa non è una soluzione solo HTML ... onerrorè JavaScript


3
Funziona benissimo. Ecco un aggiornamento con un'immagine di fallback su 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>                                            

Usa l'immagine di sfondo che ti consente di aggiungere più immagini. Il mio caso: image1 è l'immagine principale, questa verrà visualizzata da qualche punto (il browser sta facendo una richiesta) image2 è un'immagine locale predefinita da mostrare mentre image1 viene caricato. Se image1 restituisce qualsiasi tipo di errore, l'utente non vedrà alcun cambiamento e questo sarà pulito per l'esperienza dell'utente



Funziona solo se image1 è completamente opaco. Se ha trasparenza, come la maggior parte delle immagini di icone, allora image2 mostrerà attraverso.
jdunning

14
<style type="text/css">
img {
   background-image: url('/images/default.png')
}
</style>

Assicurati di inserire le dimensioni dell'immagine e se vuoi che l'immagine venga affiancata o meno.


28
La maggior parte dei browser non mostra un'immagine "link non funzionante" quando l'immagine non viene trovata ... In tal caso, l'impostazione dello sfondo non risolve il problema.
Justin D.

13

Non penso sia possibile usare solo HTML. Comunque usando javascript questo dovrebbe essere fattibile. Bassicamente passiamo su ogni immagine, testiamo se è completa e se è naturale La larghezza è zero, significa che non è stata trovata. Ecco il codice:

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

Usalo in questo modo:

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

Testato su Chrome e Firefox


2
Funziona con Pim ed è totalmente riutilizzabile, ma preferirei l'opzione leggera proprio per questo caso. Grazie mille :) +1
Galilyou,

Mi hai salvato tutta la vita, signore.
Beardminator

12

Se stai usando Angular / jQuery, questo potrebbe aiutare ...

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

Spiegazione

Supponendo che itemabbia una proprietà urlche potrebbe essere nulla, quando è allora l'immagine apparirà come rotta. Ciò innesca l'esecuzione onerrordell'espressione dell'attributo, come descritto sopra. Devi sovrascrivere l' srcattributo come descritto sopra, ma avrai bisogno di jQuery per accedere a altSrc. Impossibile farlo funzionare con JavaScript vaniglia.

Potrebbe sembrare un po 'confuso, ma ha salvato la giornata sul mio progetto.


11

un semplice elemento img non è molto flessibile, quindi l'ho combinato con un elemento immagine. in questo modo non è necessario alcun CSS. quando si verifica un errore, tutti gli srcset sono impostati sulla versione di fallback. l'immagine di un collegamento interrotto non viene visualizzata. non carica versioni di immagini non necessarie. l'elemento picture supporta il design reattivo e più fallback per tipi che non sono supportati dal 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>

questo è fantastico! prestare attenzione al supporto del browser mancante caniuse.com/#feat=picture . considerare l'utilizzo di un polyfill o di un'altra soluzione se è necessario supportare browser meno recenti come IE11.
Hinrich,

7

angular2:

<img src="{{foo.url}}" onerror="this.src='path/to/altimg.png'">

1
Mentre questo può funzionare, non penso che aggiunga nuove informazioni. La parte onerror è solo JavaScript vaniglia e l'associazione src dovrebbe già essere nota agli utenti Angular
Chic

7

Soluzione semplice e accurata che coinvolge alcune buone risposte e commenti.

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

Risolve persino il rischio di loop infinito.

Ha funzionato per me.


IMO, questo sicuramente non sembra elegante.
Script47

1
@ Script47 È pulito, ripeto pulito
maniacale kumar il

1
No, non direi neanche che sia pulito. Per non parlare del fatto che si tratta probabilmente di una nuova versione di altre soluzioni.
Script47

Funziona come un fascino! Grazie!
Goehybrid,

1
Salvavita. Non volevo elegante, volevo semplice e funzionante. Grazie!
Kit

7

Una soluzione solo HTML, in cui l'unico requisito è conoscere la dimensione dell'immagine che si sta inserendo. Non funzionerà con immagini trasparenti, in quanto utilizza background-imagecome riempitivo.

Possiamo usare con successo background-imageper collegare l'immagine che appare se manca l'immagine data. Quindi l'unico problema è l'immagine dell'icona rotta: possiamo rimuoverla inserendo un carattere vuoto molto grande, spingendo così il contenuto al di fuori della visualizzazione di 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 soluzione solo 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


4

Non c'è modo di essere sicuri del numero innumerevole di client (browser) che proveranno a visualizzare la tua pagina. Un aspetto da considerare è che i client di posta elettronica sono defacto browser Web e potrebbero non gestire tale inganno ...

Come tale dovresti anche includere un alt / testo con una LARGHEZZA PREDEFINITA e ALTEZZA, come questa. Questa è una soluzione HTML pura.

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

Quindi l'altra buona risposta sarebbe leggermente modificata come segue:

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

Ho avuto problemi con il tag object in Chrome, ma immagino che questo si applicherebbe anche a quello.

Puoi dare ulteriore stile all'alt / text per essere MOLTO GRANDE ...

Quindi la mia risposta è usare Javascript con un bel fallback di testo / alt.

Ho anche trovato questo interessante: come modellare l'attributo alt di un'immagine


3

Una versione modulabile con JQuery , aggiungi questo alla fine del tuo 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>

e sul tuo imgtag:

<img src="..." data-src-error="..." />

3

La soluzione sopra è incompleta , manca l'attributo src.

this.srce this.attribute('src')NON sono gli stessi, il primo contiene il riferimento completo all'immagine, ad esempio http://my.host/error.jpg, ma l'attributo mantiene solo il valore originale,error.jpg

Soluzione corretta

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

3
Quando uso questo codice, vedo Uncaught TypeError: this.attribute is not a functionin Chrome 43.
John Washam,

Stai usando jQuery?
mix3d

onError è obsoleto come da developer.mozilla.org/en-US/docs/Web/HTML/Element/img
comiventor

2

Se si utilizza Angular 1.x è possibile includere una direttiva che consentirà di eseguire il fallback a qualsiasi numero di immagini. L'attributo fallback supporta un singolo URL, più URL all'interno di un array o un'espressione angolare utilizzando i dati dell'ambito:

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

Aggiungi una nuova direttiva di fallback al modulo dell'app angolare:

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

Bella idea! Una serie di immagini di fallback è una buona implementazione
Z. Khullah,

1

Di recente ho dovuto costruire un sistema di fallback che includesse un numero qualsiasi di immagini di fallback. Ecco come l'ho fatto usando una semplice funzione 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;
}

Sento che è un modo piuttosto leggero di gestire molte immagini di fallback.



0

Usando Jquery potresti fare qualcosa del genere:

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

Per qualsiasi immagine, basta usare questo codice javascript:

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

dove ptImageè un <img>indirizzo tag ottenuto da document.getElementById().


0

Google ha gettato questa pagina nelle parole chiave "image fallback html", ma poiché nessuna delle precedenti mi ha aiutato e stavo cercando un "supporto svg fallback per IE inferiore a 9", ho continuato a cercare e questo è quello che ho trovato:

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

Potrebbe essere fuori tema, ma ha risolto il mio problema e potrebbe aiutare anche qualcun altro.


0

Oltre alla brillante risposta di Patrick , per quelli di voi che cercano una soluzione js angolare multipiattaforma, ecco qui:

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

Ecco un brano in cui stavo giocando cercando di trovare la soluzione giusta: http://plnkr.co/edit/nL6FQ6kMK33NJeW8DVDY?p=preview


0

Se hai creato un progetto Web dinamico e hai inserito l'immagine richiesta in WebContent, puoi accedere all'immagine utilizzando il codice riportato di seguito in Spring MVC:

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

È inoltre possibile creare una cartella denominata img e posizionare l'immagine all'interno della cartella img e posizionare quella cartella img all'interno di WebContent, quindi è possibile accedere all'immagine utilizzando il codice riportato di seguito:

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

-2

Bene!! Ho trovato questo modo conveniente, controlla che l'attributo height dell'immagine sia 0, quindi puoi sovrascrivere l'attributo src con l'immagine predefinita: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/ Immagine

 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');
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.