Saisie d'une image par défaut au cas où l'attribut src d'un html <img> n'est pas valide?


268

Existe-t-il un moyen de rendre une image par défaut dans une <img>balise HTML , au cas où l' srcattribut n'est pas valide (en utilisant uniquement du HTML)? Sinon, quelle serait votre façon légère de contourner ce problème?


3
HTML n'a pas de solution de rechange pour les images cassées. Vous devez utiliser JavaScript pour rechercher des images cassées et modifier leur attribut src.
Blixt

2
@Blixt - Et si votre client est MS Outlook ou un autre lecteur EMAIL et que vous n'avez pas Javascript, et que l'option objet ne fonctionne pas ... Je suppose que la seule solution est alt / text
Xofo

Réponses:


319

Vous avez demandé une solution HTML uniquement ...

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

Puisque la première image n'existe pas, le repli (les sprites utilisés sur ce site Web *) s'affichera. Et si vous utilisez un très ancien navigateur qui ne prend pas en charge object, il ignorera cette balise et l'utilisera img. Voir le site Web de caniuse pour la compatibilité. Cet élément est largement pris en charge par tous les navigateurs d'IE6 +.

* Sauf si l'URL de l'image a changé (à nouveau), auquel cas vous verrez probablement le texte alternatif.


3
Cela a fonctionné pour moi dans IE8 après avoir mis la DTD pour HTML 4.01.
Patrick McElhaney

Cela ne fonctionne pas si l'image non existante est X-Frame-Optionsdéfinie sur SAMEORIGINou un paramètre plus permissif.
Attila O.

Cela fonctionne mais si le lien dans object.data n'est pas fiable, il peut charger toutes sortes de choses ...
Michael_Scharf

1
L'élément «img» ne peut pas être imbriqué dans l'élément «objet».
Matheus Miranda

2
@Matheus Bien sûr que c'est possible. En HTML4, l'objet peut contenir du contenu de flux (presque tout, y compris img), et en HTML5 il est transparent, ce qui signifie qu'il peut contenir n'importe quel HTML5 valide.
Patrick McElhaney

318

Cela fonctionne bien pour moi. Peut-être que vous voulez utiliser JQuery pour accrocher l'événement.

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

Mis à jour avec le garde d'erreur jacquargs

Mise à jour: solution CSS uniquement J'ai récemment vu Vitaly Friedman démo une excellente solution CSS que je ne connaissais pas. L'idée est d'appliquer la contentpropriété à l'image cassée. Normalement :afterou :beforene s'appliquent pas aux images, mais lorsqu'elles sont cassées, elles sont appliquées.

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

Démo: https://jsfiddle.net/uz2gmh2k/2/

Comme le montre le violon, l'image cassée elle-même n'est pas supprimée, mais cela résoudra probablement le problème dans la plupart des cas sans JS ni gouttes de CSS. Si vous devez appliquer différentes images à différents endroits, différenciez-les simplement avec une classe:.my-special-case img:before { ...


3
À mon avis. C'est la meilleure réponse. Voici quirksmodes prendre surerror ..... semble assez sûr pour moi. quirksmode.org/dom/events/error.html#t01
n0nag0n

12
BTW, si error.jpg n'existe pas, cela provoque une boucle infinie car il continue d'essayer de trouver l'image, puis onError est appelé à nouveau, il ne peut pas la trouver et le tout recommence.
borq

30
Pour éviter le risque de boucle infinie, ajoutez simplement un test: <img src = "foo.jpg" onerror = "if (this.src! = 'Error.jog') this.src = 'error.jpg';">
jacquarg

21
Alternativement, vous pouvez écrire:onerror="this.src='error.jpg';this.onerror='';"
Denilson Sá Maia

6
Où est jQuery dans tout cela?
Praveen Kumar Purushothaman

64

J'ai trouvé cette solution dans Spring in Action 3rd Ed.

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

Mise à jour: Ce n'est pas une solution uniquement HTML ... onerrorest javascript


3
Cela fonctionne très bien. Voici une mise à jour avec une image de secours sur 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>                                            

Utilisez une image d'arrière-plan qui vous permet d'ajouter plusieurs images. Mon cas: image1 est l'image principale, cela proviendra d'un endroit (navigateur faisant une demande) image2 est une image locale par défaut à afficher pendant le chargement de l'image1. Si image1 renvoie n'importe quel type d'erreur, l'utilisateur ne verra aucun changement et ce sera propre pour l'expérience utilisateur



Cela ne fonctionne que si image1 est complètement opaque. S'il a de la transparence, comme la plupart des images d'icônes, l'image2 apparaîtra.
jdunning

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

Assurez-vous de saisir les dimensions de l'image et si vous souhaitez que l'image soit tuile ou non.


28
La plupart des navigateurs n'affichent-ils pas une image de «lien rompu» lorsque l'image n'est pas trouvée ... Dans ce cas, la définition de l'arrière-plan ne résoudrait pas le problème.
Justin D.

13

Je ne pense pas que ce soit possible en utilisant uniquement du HTML. Cependant, en utilisant javascript, cela devrait être possible. Bassicly, nous bouclons sur chaque image, testons si elle est complète et si sa largeur naturelle est nulle, cela signifie qu'elle n'a pas été trouvée. Voici le 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;
        }
    }
}

Utilisez-le comme ceci:

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

Testé dans Chrome et Firefox


2
Cela fonctionne Pim, et il est totalement réutilisable, mais je préférerais l'option légère pour ce cas. Merci beaucoup :) +1
Galilyou

Vous avez sauvé toute ma vie monsieur.
Beardminator

12

Si vous utilisez Angular / jQuery, cela pourrait vous aider ...

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

Explication

En supposant qu'il itempossède une propriété urlqui pourrait être nulle, quand c'est le cas, l'image apparaîtra comme cassée. Cela déclenche l'exécution de l' onerrorexpression d'attribut, comme décrit ci-dessus. Vous devez remplacer l' srcattribut comme décrit ci-dessus, mais vous aurez besoin de jQuery pour accéder à votre altSrc. Impossible de le faire fonctionner avec du JavaScript vanille.

Cela peut sembler un peu hacky mais a sauvé la mise sur mon projet.


11

un élément img simple n'est pas très flexible, je l'ai donc combiné avec un élément image. de cette façon, aucun CSS n'est nécessaire. lorsqu'une erreur se produit, tous les srcset sont définis sur la version de secours. une image de lien cassé ne s'affiche pas. il ne charge pas les versions d'image inutiles. l'élément d'image prend en charge une conception réactive et plusieurs solutions de rechange pour les types qui ne sont pas pris en charge par le navigateur.

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

celui-ci est super! soyez conscient du manque de support du navigateur caniuse.com/#feat=picture . pensez à utiliser un polyfill ou une autre solution si vous devez prendre en charge des navigateurs plus anciens comme IE11.
Hinrich

7

angular2:

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

1
Bien que cela puisse fonctionner, je ne pense pas que cela ajoute de nouvelles informations. La partie onerror est juste du vanilla JavaScript et la liaison src devrait déjà être connue des utilisateurs Angular
Chic

7

Solution simple et soignée impliquant de bonnes réponses et commentaires.

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

Il résout même le risque de boucle infinie.

A travaillé pour moi.


OMI, cela n'a certainement pas l'air élégant.
Script47

1
@ Script47 C'est soigné, je répète soigné
manish kumar

1
Non, je ne dirais pas non plus que c'est bien. Sans oublier qu'il s'agit probablement d'une refonte d'autres solutions.
Script47

Fonctionne comme un charme! Je vous remercie!
Goehybrid

1
Gareautrain. Je ne voulais pas élégant, je voulais simple et fonctionnel. Merci!
Kit

7

Une solution HTML uniquement, où la seule exigence est que vous connaissiez la taille de l'image que vous insérez. Ne fonctionnera pas pour les images transparentes, car il sert background-imagede remplissage.

Nous pouvons utiliser avec succès background-imagepour lier l'image qui apparaît si l'image donnée est manquante. Ensuite, le seul problème est l'image de l'icône cassée - nous pouvons la supprimer en insérant un très grand caractère vide, poussant ainsi le contenu en dehors de l'affichage 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


Une solution CSS uniquement (Webkit uniquement)

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

Il n'y a aucun moyen d'être sûr du nombre innombrable de clients (navigateurs) qui tenteront d'afficher votre page. Un aspect à prendre en compte est que les clients de messagerie sont des navigateurs Web de facto et peuvent ne pas gérer de tels trucs et astuces ...

En tant que tel, vous devez également inclure un alt / texte avec une LARGEUR ET UNE HAUTEUR PAR DÉFAUT, comme ceci. Il s'agit d'une solution HTML pure.

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

Donc, l'autre bonne réponse serait légèrement modifiée comme suit:

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

J'ai eu des problèmes avec la balise d'objet dans Chrome, mais j'imagine que cela s'appliquerait également à cela.

Vous pouvez en outre styler l'alt / texte pour être TRÈS GRAND ...

Donc ma réponse est d'utiliser Javascript avec une belle alternative alt / text.

J'ai également trouvé cela intéressant: comment styliser l'attribut alt d'une image


3

Une version modulable avec JQuery , ajoutez ceci à la fin de votre fichier:

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

et sur votre imgtag:

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

3

La solution ci-dessus est incomplète , il a manqué l'attribut src.

this.srcet ne this.attribute('src')sont PAS les mêmes, la première contient la référence complète à l'image, par exemple http://my.host/error.jpg, mais l'attribut conserve simplement la valeur d'origine,error.jpg

Solution correcte

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

3
Lors de l'utilisation de ce code, je vois Uncaught TypeError: this.attribute is not a functiondans Chrome 43.
John Washam

Utilisez-vous jQuery?
mix3d

onError est déconseillé selon developer.mozilla.org/en-US/docs/Web/HTML/Element/img
comiventor

2

Si vous utilisez Angular 1.x, vous pouvez inclure une directive qui vous permettra de revenir à n'importe quel nombre d'images. L'attribut de secours prend en charge une seule URL, plusieurs URL à l'intérieur d'un tableau ou une expression angulaire utilisant des données de portée:

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

Ajoutez une nouvelle directive de secours à votre module d'application angulaire:

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

Idée sympa! Un tableau d'images de secours est une bonne implémentation
Z. Khullah

1

J'ai récemment dû créer un système de secours qui comprenait un nombre illimité d'images de secours. Voici comment je l'ai fait en utilisant une simple fonction 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;
}

J'ai l'impression que c'est une façon assez légère de gérer de nombreuses images de secours.



0

En utilisant Jquery, vous pourriez faire quelque chose comme ceci:

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

Pour n'importe quelle image, utilisez simplement ce code javascript:

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

ptImageest une <img>adresse de balise obtenue par document.getElementById().


0

Google a jeté cette page aux mots clés "image fallback html", mais parce que rien de ce qui précède ne m'a aidé, et je cherchais un "support de secours svg pour IE en dessous de 9", j'ai continué à chercher et voici ce que j'ai trouvé:

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

Cela peut être hors sujet, mais cela a résolu mon propre problème et cela pourrait aussi aider quelqu'un d'autre.


0

En plus de la brillante réponse de Patrick , pour ceux d'entre vous qui recherchent une solution js angulaire multiplateforme, c'est parti:

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

Voici un plunk où je jouais en essayant de trouver la bonne solution: http://plnkr.co/edit/nL6FQ6kMK33NJeW8DVDY?p=preview


0

Si vous avez créé un projet Web dynamique et avez placé l'image requise dans WebContent, vous pouvez accéder à l'image en utilisant le code mentionné ci-dessous dans Spring MVC:

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

Vous pouvez également créer un dossier nommé img et placer l'image dans le dossier img et placer ce dossier img dans WebContent, puis vous pouvez accéder à l'image en utilisant le code mentionné ci-dessous:

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

-2

Bien!! J'ai trouvé cette méthode pratique, vérifiez que l'attribut height de l'image est égal à 0, puis vous pouvez remplacer l'attribut src par l'image par défaut: 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');
  }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.