Wprowadzanie domyślnego obrazu w przypadku, gdy atrybut src html <img> jest nieprawidłowy?


268

Czy jest jakiś sposób na renderowanie domyślnego obrazu w <img>znaczniku HTML na wypadek, gdyby srcatrybut był nieprawidłowy (używając tylko HTML)? Jeśli nie, jaki byłby twój lekki sposób na obejście tego?


3
HTML nie ma efektu zastępczego dla uszkodzonych obrazów. Musisz użyć JavaScript, aby znaleźć uszkodzone obrazy i zmienić ich atrybut src.
Blixt,

2
@Blixt - Co jeśli twój klient to MS Outlook lub inny czytnik EMAIL, a nie masz Javascript, a opcja obiektu nie działa ... Zakładam, że jedynym rozwiązaniem jest alt / text
Xofo

Odpowiedzi:


319

Poprosiłeś o rozwiązanie tylko 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>

Ponieważ pierwszy obraz nie istnieje, wyświetli się kreacja zastępcza (duszki używane na tej stronie *). A jeśli używasz naprawdę starej przeglądarki, która nie obsługuje object, zignoruje ten tag i użyje imgtagu. Zobacz stronę internetową caniuse dla kompatybilności. Ten element jest szeroko obsługiwany przez wszystkie przeglądarki z IE6 +.

* Chyba że adres URL obrazu zostanie zmieniony (ponownie), w takim przypadku prawdopodobnie zobaczysz tekst alternatywny.


3
Działa dla mnie w IE8 po tym, jak wstawiłem DTD dla HTML 4.01.
Patrick McElhaney

To nie działa, jeśli nieistniejący obraz ma X-Frame-Optionsustawione SAMEORIGINlub bardziej liberalne ustawienie.
Attila O.

Działa, ale jeśli link w obiekcie object.data nie jest zaufany, może załadować różne rzeczy ...
Michael_Scharf,

1
Element „img” nie może być zagnieżdżony w elemencie „object”.
Matheus Miranda

2
@ Matheus Pewnie, że może. W HTML4 obiekt może zawierać treść przepływu (prawie wszystko, w tym img), aw HTML5 jest przezroczysty, co oznacza, że ​​może zawierać dowolny prawidłowy HTML5.
Patrick McElhaney

318

To działa dobrze dla mnie. Być może chcesz użyć JQuery do przechwycenia zdarzenia.

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

Zaktualizowany o zabezpieczenie przed błędami jacquargs

Zaktualizowano: tylko rozwiązanie CSS Ostatnio widziałem demo Witalija Friedmana świetne rozwiązanie CSS, o którym nie wiedziałem. Chodzi o zastosowanie contentwłaściwości do uszkodzonego obrazu. Zwykle :afterlub :beforenie mają zastosowania do obrazów, ale gdy są uszkodzone, są stosowane.

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

Jak pokazuje skrzypce, sam zepsuty obraz nie jest usuwany, ale prawdopodobnie rozwiąże to problem w większości przypadków bez JS i plików CSS. Jeśli chcesz zastosować różne obrazy w różnych lokalizacjach, po prostu różnicuj za pomocą klasy:.my-special-case img:before { ...


3
W mojej opinii. To lepsza odpowiedź. Oto dziwne tryby nabierały na siebie ... wydaje mi się dość bezpieczne. quirksmode.org/dom/events/error.html#t01
n0nag0n

12
BTW, jeśli błąd.jpg nie istnieje, powoduje to nieskończoną pętlę, ponieważ ciągle próbuje znaleźć obraz, a następnie onError jest wywoływany ponownie, nie może go znaleźć, a wszystko zaczyna się od nowa.
borq

30
Aby uniknąć ryzyka nieskończonej pętli, po prostu dodaj test: <img src = "foo.jpg" onerror = "if (this.src! = 'Error.jog') this.src = 'error.jpg';">
jacquarg

21
Możesz też napisać:onerror="this.src='error.jpg';this.onerror='';"
Denilson Sá Maia

6
Gdzie jest w tym jQuery?
Praveen Kumar Purushothaman

64

Znalazłem to rozwiązanie w Spring in Action 3rd Ed.

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

Aktualizacja: To nie jest tylko rozwiązanie HTML ... onerrorto javascript


3
To działa świetnie. Oto aktualizacja z rezerwowym obrazem na 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>                                            

Użyj obrazu tła, który pozwala dodać wiele obrazów. Mój przypadek: obraz1 jest głównym obrazem, który otrzyma z jakiegoś miejsca (przeglądarka wykonuje żądanie) obraz2 jest domyślnym obrazem lokalnym wyświetlanym podczas ładowania obrazu1. Jeśli obraz 1 zwróci jakikolwiek błąd, użytkownik nie zobaczy żadnej zmiany i będzie to czyste dla wygody użytkownika



Działa to tylko wtedy, gdy obraz1 jest całkowicie nieprzezroczysty. Jeśli ma przezroczystość, jak większość obrazów ikon, to obraz2 przejdzie przez.
jdunning

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

Pamiętaj o wprowadzeniu wymiarów obrazu i określ, czy obraz ma być kafelkowy, czy nie.


28
Czy większość przeglądarek nie wyświetla obrazu „zepsutego łącza”, gdy obraz nie został znaleziony ... W takim przypadku ustawienie tła nie rozwiązałoby problemu.
Justin D.,

13

Nie sądzę, że jest to możliwe przy użyciu samego HTML. Jednak przy użyciu javascript powinno to być wykonalne. Basowo zapętlamy każdy obraz, sprawdzamy, czy jest on kompletny, a jeśli jest naturalny Szerokość wynosi zero, to znaczy, że nie został znaleziony. Oto kod:

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

Użyj tego w ten sposób:

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

Testowane w Chrome i Firefox


2
Działa Pim i jest całkowicie wielokrotnego użytku, ale wolałbym lekką opcję w tym przypadku.
Wielkie

Uratowałeś mi całe życie.
Beardminator

12

Jeśli używasz Angular / jQuery, może to pomóc ...

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

Wyjaśnienie

Zakładając, że itemma właściwość, urlktóra może mieć wartość NULL, wtedy jest ona wyświetlana jako uszkodzona. To powoduje wykonanie onerrorwyrażenia atrybutu, jak opisano powyżej. Musisz przesłonić srcatrybut, jak opisano powyżej, ale będziesz potrzebować jQuery, aby uzyskać dostęp do altSrc. Nie można go uruchomić z waniliowym JavaScript.

Może wydawać się trochę zrzędliwy, ale uratował mi dzień w moim projekcie.


11

prosty element img nie jest zbyt elastyczny, więc połączyłem go z elementem obrazu. w ten sposób nie jest potrzebny CSS. gdy wystąpi błąd, wszystkie srcset są ustawione na wersję rezerwową. uszkodzony link nie wyświetla się. nie ładuje niepotrzebnych wersji obrazu. element obrazu obsługuje responsywne projektowanie i liczne awarie dla typów, które nie są obsługiwane przez przeglądarkę.

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

ten jest świetny! pamiętaj o braku obsługi przeglądarki caniuse.com/#feat=picture . rozważ użycie wielopełniacza lub innego rozwiązania, jeśli potrzebujesz obsługi starszych przeglądarek, takich jak IE11.
Hinrich

7

angular2:

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

1
Chociaż może to działać, nie sądzę, aby dodawało to nowe informacje. Część onerror to po prostu waniliowy JavaScript, a powiązanie src powinno już być znane użytkownikom Angular
Chic

7

Proste i schludne rozwiązanie obejmujące kilka dobrych odpowiedzi i komentarzy.

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

Rozwiązuje nawet ryzyko nieskończonej pętli.

Pracował dla mnie.


IMO, to zdecydowanie nie wygląda elegancko.
Script47

1
@ Script47 Jest schludny, powtarzam schludny
manish kumar

1
Nie, nie powiedziałbym też, że jest fajnie. Nie wspominając już o tym, że jest to prawdopodobnie powtórka innych rozwiązań.
Script47

Działa jak marzenie! Dziękuję Ci!
Goehybrid,

1
Ratownik. Nie chciałem eleganckiego, chciałem prosty i działający. Dzięki!
Kit

7

Rozwiązanie tylko w języku HTML, w którym jedynym wymaganiem jest znajomość rozmiaru wstawianego obrazu. Nie działa w przypadku przezroczystych obrazów, ponieważ wykorzystuje się go background-imagejako wypełniacz.

Możemy z powodzeniem użyć background-imagedo połączenia obrazu, który pojawia się, jeśli brakuje danego obrazu. Wtedy jedynym problemem jest zepsuty obraz ikony - możemy go usunąć, wstawiając bardzo duży pusty znak, a tym samym wypychając zawartość poza ekran 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


Rozwiązanie tylko CSS (tylko 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

Nie ma sposobu, aby upewnić się, że niezliczona liczba klientów (przeglądarek), które spróbują wyświetlić Twoją stronę. Jednym z aspektów, które należy wziąć pod uwagę, jest to, że klienci poczty e-mail są defaktami przeglądarek internetowych i mogą nie obsługiwać takich sztuczek ...

Jako taki, powinieneś także dołączyć alt / text z DOMYŚLNĄ SZEROKOŚCIĄ i WYSOKOŚCIĄ, w ten sposób. To jest czyste rozwiązanie HTML.

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

Tak więc inna dobra odpowiedź zostałaby nieco zmodyfikowana w następujący sposób:

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

Miałem problemy z tagiem obiektu w Chrome, ale wyobrażam sobie, że to dotyczy również tego.

Możesz dodatkowo stylizować alt / tekst, aby był BARDZO WIELKI ...

Tak więc moją odpowiedzią jest użycie Javascript z ładnym odwróceniem tekstu alt / text.

Dla mnie też było interesujące: Jak stylizować atrybut alt obrazu


3

Modulowana wersja z JQuery , dodaj to na końcu pliku:

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

i na twoim imgtagu:

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

3

Powyższe rozwiązanie jest niekompletne , brakowało atrybutu src.

this.srci this.attribute('src')NIE są takie same, pierwszy zawiera na przykład pełne odniesienie do obrazu http://my.host/error.jpg, ale atrybut zachowuje oryginalną wartość,error.jpg

Prawidłowe rozwiązanie

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

3
Gdy używam tego kodu, widzę Uncaught TypeError: this.attribute is not a functionw Chrome 43.
John Washam

Czy używasz jQuery?
mix3d

onError jest przestarzałe jak na developer.mozilla.org/en-US/docs/Web/HTML/Element/img
komentator

2

Jeśli używasz Angulara 1.x, możesz dołączyć dyrektywę, która pozwoli ci wrócić do dowolnej liczby obrazów. Atrybut rezerwowy obsługuje pojedynczy adres URL, wiele adresów URL w tablicy lub wyrażenie kątowe przy użyciu danych zakresu:

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

Dodaj nową dyrektywę zastępczą do modułu aplikacji kątowej:

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

Fajny pomysł! Tablica z rezerwowych obrazów jest dobrą implementacją
Z. Khullah

1

Niedawno musiałem zbudować system rezerwowy, który obejmował dowolną liczbę obrazów rezerwowych. Oto jak to zrobiłem za pomocą prostej funkcji 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;
}

Wydaje mi się, że jest to dość lekki sposób radzenia sobie z wieloma obrazami zastępczymi.



0

Za pomocą Jquery możesz zrobić coś takiego:

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

W przypadku dowolnego obrazu użyj tego kodu javascript:

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

gdzie ptImagejest <img>adres tagu uzyskany przez document.getElementById().


0

Google wyrzuciło tę stronę do słów kluczowych „obraz zastępczy html”, ale ponieważ nie powyższe pomogło mi, i szukałem „wsparcia zastępczego svg dla IE poniżej 9”, szukałem dalej i oto, co znalazłem:

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

To może być nie na temat, ale rozwiązało mój własny problem i może pomóc komuś innemu.


0

Oprócz genialnej odpowiedzi Patricka , dla tych z was, którzy szukają międzyplatformowego rozwiązania kątowego js, ​​proszę:

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

Oto problem, w którym grałem, próbując znaleźć właściwe rozwiązanie: http://plnkr.co/edit/nL6FQ6kMK33NJeW8DVDY?p=preview


0

Jeśli utworzyłeś dynamiczny projekt internetowy i umieściłeś wymagany obraz w WebContent, możesz uzyskać dostęp do obrazu przy użyciu niżej wymienionego kodu w Spring MVC:

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

Możesz również utworzyć folder o nazwie img i umieścić obraz w folderze img i umieścić ten folder img w WebContent, a następnie możesz uzyskać dostęp do obrazu za pomocą poniższego kodu:

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

-2

Dobrze!! Uznałem to za wygodne, sprawdź, czy atrybut wysokości obrazu ma wartość 0, a następnie możesz zastąpić atrybut src domyślnym obrazem: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/ Wizerunek

 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');
  }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.