How to style "broken image" (when image does not load)

Asked

Viewed 1,082 times

6

How would it be possible to make a CSS style for when the image is not loaded on the page?

When you have the link to the image, but for some reason it is not loaded on the page, or if the link or image path is wrong, or even if the image is not in the correct folder or on the server, it would be possible to create a CSS style to handle these broken images?

The normal thing to see is when the image does not load:

inserir a descrição da imagem aqui

But I would like something more customized with CSS like this:

inserir a descrição da imagem aqui

  • 1

    Does this solution not solve? https://bitsofco.de/styling-broken-images/

  • 1

    It’s well out there @Ricardopunctual if you want to create an example ai as a response to get registered on the site more consistently!

  • @hugocsl good initiative +1. I gave an answer. I think the way is the same JS.

  • Attribute alt. If the image does not appear (if it has the wrong address or the images are disabled) or if the user uses a screen reader, alt="deu ruim"

  • @Wallacemaxters even liked there, but has how to do with CSS tb I believe! Not that one option is better than the other...

  • @Exact leocaracciolo is just that, but wanted to treat this standard behavior to leave a message better formatted for the user

  • 1

    @hugocsl wrote a reply with the content of the link, with a basic explanation of how it works, for reference if the link is no longer available tomorrow :)

Show 2 more comments

3 answers

7


Well, I don’t know if there’s any way to solve this just through CSS, but what I usually do is use the event onerror to capture when there is a failure when opening the image.

thus:

    document.querySelector('img').addEventListener('error', function() {                  
             // sua lógica aqui.
    }) 

It is common to define another src for the image, but you could also add a class to the image, or replace it with another element.

Example:

document.querySelector('.error').addEventListener('error', function () {

    var div = document.createElement('div');

    div.classList.add('img-error');
    div.innerText = 'Imagem falhou';

    this.replaceWith(div)
})
.img-error{
    background-color: #ccc;
    width: 100px;
    height: 100px;
    display: inline-flex;
    justify-contents: center;
    align-items: center;
    
}
<img src="https://i.stack.imgur.com/CF2nj.jpg?s=48&g=1">
<img src="nao_existe" class="error">

Observing: If you choose to exchange the src of the image in onerror, make sure the fallback image used to "cover the error" actually exists, otherwise it will cause an infinite loop in the call onerror (already happened to me when I forgot to publish an image that represented the user without a photo).

Option 2

Another thing I like to do is wear background-image in a div with predefined formatting (a background-color for example). Thus, when the image fails to load, the background-color will be there to make the fallback.

  • 3

    Well pasta, thanks for the contribution!

5

Solution-based bitsofcode: https://bitsofco.de/styling-broken-images/

img {
  font-family: 'Helvetica';
  font-weight: 300;
  line-height: 2;  
  text-align: center;
  
  width: 100%;
  height: auto;
  display: block;
  position: relative;
  min-height: 50px;
}
/*
:before pode ser cobrido pela imagem, mas quando a imagem está quebrada ele fica visível
*/
img:before { 
  content: " ";
  display: block;

  position: absolute;
  top: -10px;
  left: 0;
  height: calc(100% + 10px);
  width: 100%;
  background-color: rgb(230, 230, 230);
  border: 2px dotted rgb(200, 200, 200);
  border-radius: 5px;
}
/*
:after mesmo comportamento de :before em relação à imagem
*/
img:after { 
  /* \f127 e a imagem de um link, do FontAwesome
     attr() pega um atributo do elemento, aqui pegando o "alt"
  */
  content: "\f127" " Imagem quebrada: '"  attr(alt) "'";
  display: block;
  font-size: 16px;
  font-style: normal;
  font-family: FontAwesome;
  color: rgb(100, 100, 100);
  
  position: absolute;
  top: 5px;
  left: 0;
  width: 100%;
  text-align: center;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">

<img src="image-que-nao-existe.jgp" alt="alguma imagem" />

I added just a few basic comments and a minimal change.
In the original English link, there is an explanation of the use of :before and :after, in free translation:

The element <img> is a replaced element. This is an element "whose appearance and dimensions are defined by an external resource" (Sitepoint). As the element is controlled by an external source, the pseudo-elements :before and :after normally should not work with it. However, when the image is broken and is not loaded, these pseudo-elements may appear.

EDIT taking advantage of @Guilherme’s suggestion, tested in the browsers:
- Worked on Chrome 68, Chrome on Android, Firefox 61 and Opera 36 (medium old)
- Didn’t work on IE 9/11, Edge got weird

  • Legal Ricardo thanks for the reply!

  • 1

    As I commented in the chat for hugocsl, check the support for this, this is a feature that in VOID elements is unusual, currently FF and Chrome support, but mobiles, msedge and other situations will probably not be able to have the same effect.

  • It is true, I had done some tests and unfortunately only serve for FF and Chrome

3

I used any CSS but you put your.

Pure Javascript

At the event onerror (which is triggered if an error occurs while loading the image) call a function to change the contents of the div that contains the image

Example 1

function img_erro(){
   var element = document.getElementById("trap_section");
   element.innerHTML = '<div id="trap_top1" style=""></div><div id="section1"><div class="indent"><div><h1>Erro ao carregar imagem</h1><p>Deu ruim</p></div></div></div><div id="trap_bottom1" style=""></div>';
}
            .trap_section{
                position: relative;
                width: 500px;
                border: none;
                margin-top: 100px;
            }
            #trap_top1{
                position: absolute;
                top: -80px;
                border-top: 80px solid transparent;
                border-right-width: 500px; border-right-style: solid; border-right-color: rgb(255, 137, 91);
            }
            #trap_bottom1{    
                position: absolute;
                bottom: -80px;
                border-bottom: 80px solid transparent;
                border-right-width: 500px; border-right-style: solid; border-right-color: rgb(255, 137, 91);
            }
            #section1{
                background: #FF895B;
                color: #FFFFFF;
                margin: 0 auto;
                overflow-y: hidden;
                height: 200px;
            }
            h1, p{text-align:center;}
 
 <div id="trap_section" class="trap_section">
      <img src="sem_url" onerror="img_erro()">
 </div>

Example 2

function myFunction() {
    document.getElementById("myDIV").className = "mystyle";
    document.getElementById("myDIV").innerHTML = 'Erro ao carregar imagem';
}
.mystyle {
    width: 300px;
    height: 50px;
    background-color: gray;
    text-align: center;
    font-size: 25px;
    color: white;
    margin-bottom: 10px;
}
<div id="myDIV">
<img src="image.gif" onerror="myFunction()">
</div>

For those who already use Jquery:

Use the jQuery error event and do any action you want if the image cannot be loaded.

  • Hide the image tag $(this).hide();
  • Add content in its place $( "#id_div").append(...

        
$("#img").on("error", function() {
    $(this).hide();
    $( "#id_div").append( '<div class="trap_section"><div id="trap_top1" style=""></div><div id="section1"><div class="indent"><div><h1>Erro ao carregar imagem</h1><p>Deu ruim</p></div></div></div><div id="trap_bottom1" style=""></div>');
});
    .trap_section{
                    position: relative;
                    width: 500px;
                    border: none;
                    margin-top: 100px;
                }
                #trap_top1{
                    position: absolute;
                    top: -80px;
                    border-top: 80px solid transparent;
                    border-right-width: 500px; border-right-style: solid; border-right-color: rgb(255, 137, 91);
                }
                #trap_bottom1{    
                    position: absolute;
                    bottom: -80px;
                    border-bottom: 80px solid transparent;
                    border-right-width: 500px; border-right-style: solid; border-right-color: rgb(255, 137, 91);
                }
                #section1{
                    background: #FF895B;
                    color: #FFFFFF;
                    margin: 0 auto;
                    overflow-y: hidden;
                    height: 200px;
                }
                h1, p{text-align:center;}
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <div id="id_div">
          <img id="img" src="semUrl">
        </div>

Using a standard image

<!--imagem existente -->
<img src="https://i.stack.imgur.com/CF2nj.jpg?s=48&g=1" onerror="this.onerror=null;this.src='https://i.stack.imgur.com/Mf7KP.png';" />


<!--imagem sem src -->
<img src="semSrc" onerror="this.onerror=null;this.src='https://i.stack.imgur.com/Mf7KP.png';" />

  • For those who already use jquery in the project is still an option

  • 1

    @hugocsl, I edited the answer and put it with pure javascript and jquery, so it’s comfortable with the customer :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.