::before is not displayed in <img>

Asked

Viewed 336 times

3

I created a kind of lazyload (image preloading) in Javascript with the event scroll where some images are only loaded when they enter the visible area of the window.

For this I created a generic image of 1x1 transparent pixel (dt.png) and put in the src of the images and an attribute data-src with the path of the respective image:

<img src="dt.png" data-src="img/foto1.jpg" class="lazyload">
<img src="dt.png" data-src="img/foto2.jpg" class="lazyload">

In doing scroll, the Javascript code will check if the image is inside the viewport window, if it is will replace the value of src for data-src loading and displaying the image. So far so good.

The problem is that I wish there was not an empty area in place of the image, but that there was in this area a text like "Loading image...", because sometimes the image takes a few seconds to load and gives the impression that there was some fault. Anyway, I would like the user to know that there will be displayed the image.

I tried to do this using the pseudo-class ::before on the tag <img> and even works if the src be empty:

.lazyload::before{
   content: 'Carregando imagem...';
   position: absolute;
   right: 3px;
   top: 3px;
}

div{
   width: 300px;
   background: red;
   padding: 15px;
   color: white;
   text-align: center;
}

img{
   position: relative;
   width: 300px;
   height: 200px;
}
<div>
   <img src="" data-src="img/foto1.jpg" class="lazyload">
   <p>Texto qualquer</p>
</div>

But with the src empty is not interesting because it shows the "icon of broken image" plus a border.

Now with transparent PNG, the text of ::before does not appear (even if the GNP is transparent):

.lazyload::before{
   content: 'Carregando imagem...';
   position: absolute;
   right: 3px;
   top: 3px;
}

div{
   width: 300px;
   background: red;
   padding: 15px;
   color: white;
   text-align: center;
}

img{
   position: relative;
   width: 300px;
   height: 200px;
}
<div>
   <img src="https://i.stack.imgur.com/Qk53m.png" data-src="img/foto1.jpg" class="lazyload">
   <p>Tem uma imagem transparante aqui em cima</p>
</div>

Analyzing in inspection of elements from the browser, I noticed that when the src is empty or with an image path that does not exist, the node of the ::before appears, but when I put a correct image path, the ::before some.

Is there any way to do this ::before be visible even with the transparent GNP in src or another possible solution for this case using CSS?

  • It is interesting that in this video this technique is used and this cropped image does not appear, maybe it is a default behavior of the browser that has changed. An idea: what if you put src - instead of transparent pixel - a gif of hourglass for loading, the same for all images, and then changed src - when scroll was made - to the right image?

  • Hi @Douglas. I also thought about the hourglass, but the images are of varied sizes and does not look cool, will be distorted.

  • I made a solution using onload of the image to be loaded and a gif for the upload that is centered on the div that the image will display inside, and disappears when the image is loaded, see on fiddle. The "click" button simulates the call the function that will be called when scrolling the page. I did not put as an answer because your question is more about solving with CSS and about clarifying the behavior of ::before, but I think it might help you anyway.

  • If you decide to use onload on images, see this page image.onload Event and browser cache, I have not studied in depth but it seems to be a problem that onload will not be triggered if the image is already in the browser cache. I didn’t have that kind of problem in the example I did in the fiddle.

  • @Douglas is, I think I’ll have to use jQuery in this, because the images do not have a container of their own and would not be able to center another image exactly in the area of the main image. I have been researching and really can not use pseudo-classes in <img> tags. Your idea is even functional, but I had a better idea where I don’t need to touch HTML. Thanks for the force

1 answer

4


There’s no point in using the pseudo-element ::before with <img>, because this tag has no content (no closing tag). Despite the confusing name, the ::before creates a pseudo-element before of the content of the element specified in the selector (i.e., in the first child position), and not before the selected element itself.

In practical terms, place the pseudoelement in an external element to the image.

  • Yeah, I’ll do it with JS anyway. Obg!

Browser other questions tagged

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