default123
default123

Reputation: 170

How to force browsers to preload image with display: none?

Firefox will not load images with display: none until they are required to be shown to the user. Chromium will stall until the image is loaded, and then display it.

With smaller file sizes, there is a brief flash if the image is not already loaded on Firefox. With larger file sizes, there is a much longer delay that will also make Chromium's stall noticeable.

I would like to have images with display: none preloaded so there is no delay when displaying them.

I have tried using Javascript to declare a new Image object, but this does not work with Firefox or Chromium.

You can cycle between images in this example with the right and left arrow keys.

<!DOCTYPE html>
<html>
<head>
<style>
body, html {
    height: 100%;
    margin: 0;
    padding: 0;
}   

.imgs {
    width:50%;
    height: 50%;
}
</style>
</head>
<body>

<img src="https://picsum.photos/200/100" style="display: block;" class="imgs">
<img src="https://picsum.photos/200/200" style="display: none;" class="imgs">

<script>
imgs = document.getElementsByClassName("imgs");

// THIS DOES NOT WORK
//~ function preloadImage(url)
//~ {
    //~ var img = new Image();
    //~ img.src = url;
//~ }

//preloadImage("myImg.jpg"); THIS DOES NOT WORK

document.onkeydown = checkKey; // directional keys

function checkKey(e) {

    if (document.activeElement.tagName != "INPUT") {

        e = e || window.event;

        switch (e.keyCode) {

            case 38:
                // up arrow
                break;

            case 40:
                // down arrow
                break;

            case 37:
                // left arrow
                imgs[0].style.display = "block";
                imgs[1].style.display = "none";
                break;

            case 39:
                // right arrow
                imgs[0].style.display = "none";
                imgs[1].style.display = "block";
                break;
        }
    }
}

</script>
</body>
</html>

Upvotes: 3

Views: 1937

Answers (1)

default123
default123

Reputation: 170

I have figured out my own solution to this problem.

I use a class called "imgBuffer" to hold images that need to be displayed immediately. Images of this class will hold the source of images that need to be readily displayed, but will not display the images themselves.

The tricky part is making sure the hidden images are in a location on screen that does not affect the layout in any way.

Notice the width and height of the hidden buffered image matches that of the displayed images. If you adjust the dimensions of the hidden image, the page may behave differently such as adding a scrollbar when it's not really necessary.

<!DOCTYPE html>
<html>
<head>
<style>
body, html {
    height: 100%;
    margin: 0;
    padding: 0;
}   

.imgs {
    width:50%;
    height: 50%;
}

.imgBuffer {
    position: absolute;
    height: 50%;
    width: 50%;
    visibility: hidden;
    z-index: -1;
}
</style>
</head>
<body>

<img src="https://picsum.photos/200/100" style="display: block;" class="imgs">
<img src="https://picsum.photos/200/200" style="display: none;" class="imgs">

<img src="https://picsum.photos/200/100" class="imgBuffer">
<img src="https://picsum.photos/200/200" class="imgBuffer">

<script>
imgs = document.getElementsByClassName("imgs");

// THIS DOES NOT WORK
//~ function preloadImage(url)
//~ {
    //~ var img = new Image();
    //~ img.src = url;
//~ }

//preloadImage("myImg.jpg"); THIS DOES NOT WORK

document.onkeydown = checkKey; // directional keys

function checkKey(e) {

    if (document.activeElement.tagName != "INPUT") {

        e = e || window.event;

        switch (e.keyCode) {

            case 38:
                // up arrow
                break;

            case 40:
                // down arrow
                break;

            case 37:
                // left arrow
                imgs[0].style.display = "block";
                imgs[1].style.display = "none";
                break;

            case 39:
                // right arrow
                imgs[0].style.display = "none";
                imgs[1].style.display = "block";
                break;
        }
    }
}

</script>
</body>
</html>

Upvotes: 3

Related Questions