Image pre-loading issue

Hi there,

I am struggling with a little issue with a practice project I am working on.
I’ve made a header with a few social media icons on the right side of it. Those icons are in black and white but the moment you hover over it they a colored version takes its place. This part all works fine. But the thing, the first time after loading the webpage and you hover over those icons, you see a little flickering. Because at that moment the image is loading in. So I want to pre-load those colored images the moment you load the site to prevent this. I found a “solution” online but that didn’t seem to work, at least not for me, maybe I do something wrong. Well this is what I basically did:

When hovering:

Within my header I have some div containers for the social media links:

    <div class="header-main-sm">
          <a target="_blank" href="https://www.facebook.com"><div 
          class="header-main-sm-fb"></div></a>
          <a target="_blank" href="https://www.instagram.com"><div 
          class="header-main-sm-in"></div></a>
    </div>

And within CSS I basically did this:

 .header-main-sm {
     width: fit-content;
     height: 100%;
     padding-right: 60px;
     display: flex;
     align-items: center;
     column-gap: 10px; 
 }

 .header-main-sm-fb {
     width: 20px;
     height: 20px;
     background-image: url(facebook.png);
    background-repeat: no-repeat;
     background-size: contain;
 }

 .header-main-sm-fb:hover {
     background-image: url(facebook-color.png); 
 }

 .header-main-sm-in {
     width: 20px;
     height: 20px;
     background-image: url(instagram.png);
     background-repeat: no-repeat;
     background-size: contain;
 }

 .header-main-sm-in:hover {
     background-image: url(instagram-color.png);
 }

The solution I found online to pre-load the images is this:

 body:after {
    position: absolute;
     width: 0;
     height: 0;
     overflow: hidden;
     z-index: -1;
     content: url(instagram-color.png) url(facebook-color.png);
 }

So this should make sure the images are pre-loaded and will stay hidden until you hover over the icons. Though yeah, somehow it doesn’t seem to work for me.
After that I also tried some other way that I found online. Trying to pre-load the images in within the head of the html document like this, but that also didn’t seem to have any effect:

<link rel="preload" href="instagram-color.png" as="image">
<link rel="preload" href="facebook-color.png" as="image">

Does anyone here has any idea’s about how to solve this problem?

hi and welcome to the forum.

i did a little of my own research just now and someone suggests that you load the image with a img element instead of as a div and then add your hover effect on the img element directly.
I think it is worth a try.

1 Like

Sometimes, adjusting the widths solves the problem, it has worked for me before. He can also give it a shot.

1 Like

yes it is good practice to assign all images a width and height to prevent flickering.
But I assumed the issue was not with the image when there was no hover effect (I assumed the hover effect was triggering the issue).

I would suggest you load both and stack them. Set the opacity, so the bottom is hidden. Then change the opacity on hover.

Hi @DutchITNewb

Could you use an svg instead of an image?

Happy coding

1 Like

@hbar1st @stephenmutheu @lasjorg @Teller

Thanks for all your suggestions guys. Very much appreciate it.
I combined to solutions of @hbar1st and @lasjorg using direct img elements and opacity.

I will show you what I did now. Not sure if this is the most “efficient code” maybe there is a better or shorter way to do it, but at least it seems to work fine now without any flickering after first loading the site haha.

html code:

    <div class="header-main-sm">
        <div class="container-fb">
            <img class="fb-bw" src="facebook.png" alt="Facebook Logo">
            <img class="fb-fc" src="facebook-color.png" alt="Facebook Logo">
        </div>
        <div class="container-in">
            <img class="in-bw" src="instagram.png" alt="Instagram Logo">
            <img class="in-fc" src="instagram-color.png" alt="Instagram 
            Logo">
        </div>

And the CSS part:

 .header-main-sm {
     width: fit-content;
     height: 100%;
     padding-right: 60px;
     display: flex;
     align-items: center;
     column-gap: 10px;
 }

 /*facebook*/
 .container-fb {
     width: 20px;
     height: 20px;
 }

 .fb-bw {
     width: 20px;
     height: 20px;  
 }

 .fb-fc {
     position: relative;
     bottom: 24px;
     z-index: -1000;
 }

 .fb-bw:hover {
     opacity: 0;
 }

 /*Instagram*/
 .container-in {
     width: 20px;
     height: 20px;
 }

 .in-bw {
     width: 20px;
     height: 20px;
 }

 .in-fc {
     position: relative;
     bottom: 24px;
     z-index: -1000;
 }

 .in-bw:hover {
     opacity: 0;
 }

Well, I’d love to hear what you guys think of this solution. Is this the correct way to put it or is there another maybe a more efficiënt way to do it? Love to learn.

And thanks again for the assistance. Very much appreciated!

1 Like

I had never heard of the opacity trick before.
I guess the only way to know if something is efficient or not is to undo the change to load both images and just load one and see what happens. I am guessing though that loading both is definitely faster on the response time wrt the hover effect.

They can stay as background images if you want that. But I kind of like it when page resources are clearly visible in the HTML.


I don’t think efficiency is much of a concern, but you could try to make the styles as generic as possible for better reuse.

  • Use utility classes and group common styles.

  • With two icons stacked, you could use :first-child and/or :last-child selectors.

  • Use CSS grid to stack elements. Using a container to stack the elements can make it more reusable.

Example
<a class="icon-stack" target="_blank" href="https://www.facebook.com">
  <div class="icon fb-icon-black"></div>
  <div class="icon fb-icon-blue"></div>
</a>
.icon-stack {
  display: grid;
  grid-template-areas: "icon";
  place-items: center;
}

.icon-stack > * {
  grid-area: icon;
}

.icon-stack .icon:last-child {
  opacity: 0;
}

.icon-stack .icon:last-child:hover {
  opacity: 1;
}

.icon {
  width: 20px;
  height: 20px;
  background-repeat: no-repeat;
  background-size: contain;
}

.fb-icon-black {
  background-image: url(facebook.png);
}

.fb-icon-blue {
  background-image: url(facebook-color.png);
}

Oh nice, those are good tips. Thanks.