Preloading CSS Images

CssImageBackgroundPreloaderPreload

Css Problem Overview


I have a hidden contact form which is deployed clicking on a button. Its fields are set as CSS background images, and they always appears a bit later than the div that have been toggled.

I was using this snippet in the <head> section, but with no luck (after I cleared the cache) :

<script>
$(document).ready(function() {
		pic = new Image();
		pic2 = new Image();
		pic3 = new Image();
		pic.src="<?php bloginfo('template_directory'); ?>/images/inputs/input1.png";
		pic2.src="<?php bloginfo('template_directory'); ?>/images/inputs/input2.png";
		pic3.src="<?php bloginfo('template_directory'); ?>/images/inputs/input3.png";
});
</script>

I'm using jQuery as my library, and it would be cool if I could use it as well for arranging this issue.

Thanks for your thoughs.

Css Solutions


Solution 1 - Css

Preloading images using CSS only

In the below code I am randomly choosing the body element, since it is one of the only elements guaranteed to exist on the page.

For the "trick" to work, we shall use the content property which comfortably allows setting multiple URLs to be loaded, but as shown, the ::after pseudo element is kept hidden so the images won't be rendered:

body::after{
   position:absolute; width:0; height:0; overflow:hidden; z-index:-1; // hide images
   content:url(img1.png) url(img2.png) url(img3.gif) url(img4.jpg);   // load images
}

enter image description here

Demo


it's better to use a sprite image to reduce http requests...(if there are many relatively small sized images) and make sure the images are hosted where HTTP2 is used.

Solution 2 - Css

I believe most of the visitors of this question are looking for the answer of "How can I preload an image before the page's render starts?" and the best solution for this problem is using <link> tag because <link> tag is capable to block the further rendering of the page. See preemptive

These two value options of rel (relationship between the current document and the linked document) attribute are most relevant with the issue:

  • prefetch : load the given resource while page rendering
  • preload : load the given resource before page rendering starts

So if you want to load a resource (in this case it's an image) before the rendering process of <body> tag starts, use:

<link rel="preload" as="image" href="IMAGE_URL">

and if you want to load a resource while <body> is rendering but you are planning to use it later on dynamically and don't wanna bother the user with loading time, use:

<link rel="prefetch" href="RESOURCE_URL">

Solution 3 - Css

I can confirm that my original code seems to work. I was casually sticking to an image with a wrong path.

Here's a test : http://paragraphe.org/slidetoggletest/test.html

<script>
    var pic = new Image();
    var pic2 = new Image();
    var pic3 = new Image();
	pic.src="images/inputs/input1.png";
	pic2.src="images/inputs/input2.png";
	pic3.src="images/inputs/input3.png";
</script>

Solution 4 - Css

http://css-tricks.com/snippets/css/css-only-image-preloading/

Technique #1

Load the image on the element's regular state, only shift it away with background position. Then move the background position to display it on hover.

#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }

Technique #2

If the element in question already has a background-image applied and you need to change that image, the above won't work. Typically you would go for a sprite here (a combined background image) and just shift the background position. But if that isn't possible, try this. Apply the background image to another page element that is already in use, but doesn't have a background image.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }

Solution 5 - Css

try with this:

var c=new Image("Path to the background image");
c.onload=function(){
   //render the form
}

With this code you preload the background image and render the form when it's loaded

Solution 6 - Css

For preloading background images set with CSS, the most efficient answer i came up with was a modified version of some code I found that did not work:

$(':hidden').each(function() {
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    tempImage = new Image();
    tempImage.src = backgroundImage;
  }
});

The massive benefit of this is that you don't need to update it when you bring in new background images in the future, it will find the new ones and preload them!

Solution 7 - Css

If you're reusing these bg images anywhere else on your site for form inputs, you probably want to use an image sprite. That way you can centrally manage your images (instead of having pic1, pic2, pic3, etc...).

Sprites are generally faster for the client, since they are only requesting one (albeit slightly larger) file from the server instead of multiple files. See SO article for more benefits:

https://stackoverflow.com/questions/1289372/css-image-sprites

Then again, this might not be helpful at all if you're just using these for one form and you really only want to load them if the user requests the contact form...might make sense though.

http://www.alistapart.com/articles/sprites

Solution 8 - Css

how about loading that background image somewhere hidden. That way it will be loaded when the page is opened and wont take any time once the form is created using ajax:

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}

Solution 9 - Css

The only way is to Base64 encode the image and place it inside the HTML code so that it doesn't need to contact the server to download the image.

This will encode an image from url so you can copy the image file code and insert it in your page like so...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}

Solution 10 - Css

You could use this jQuery plugin waitForImage or you could put you images into an hidden div or (width:0 and height:0) and use onload event on images.

If you only have like 2-3 images you can bind events and trigger them in a chain so after every image you can do some code.

Solution 11 - Css

When there is no way to modify CSS code and preload images with CSS rules for :before or :after pseudo elements another approach with JavaScript code traversing CSS rules of loaded stylesheets can be used. In order to make it working scripts should be included after stylesheets in HTML, for example, before closing body tag or just after stylesheets.

getUrls() {
    const urlRegExp = /url\(('|")?([^'"()]+)('|")\)?/;

    let urls = [];
    for (let i = 0; i < document.styleSheets.length; i++) {
        let cssRules = document.styleSheets[i].cssRules;
        for (let j = 0; j < cssRules.length; j++) {
            let cssRule = cssRules[j];
            if (!cssRule.selectorText) {
                continue;
            }

            for (let k = 0; k < cssRule.style.length; k++) {
                let property = cssRule.style[k],
                    urlMatch = cssRule.style[property].match(urlRegExp);
                if (urlMatch !== null) {
                    urls.push(urlMatch[2]);
                }
            }
        }
    }
    return urls;
}

preloadImages() {
    return new Promise(resolve => {
        let urls = getUrls(),
            loadedCount = 0;

        const onImageLoad = () => {
            loadedCount++;
            if (urls.length === loadedCount) {
                resolve();
            }
        };

        for (var i = 0; i < urls.length; i++) {
            let image = new Image();
            image.src = urls[i];
            image.onload = onImageLoad;
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    preloadImages().then(() => {
        // CSS images are loaded here
    });
});

Solution 12 - Css

If the page elements and their background images are already in the DOM (i.e. you are not creating/changing them dynamically), then their background images will already be loaded. At that point, you may want to look at compression methods :)

Solution 13 - Css

I also would like add small notice.

Answer "Preloading images using CSS only" perfectly works if you do not disable the cache in dev console settings at the network tab. Otherwise it will double load the images.

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPeanutsView Question on Stackoverflow
Solution 1 - CssvsyncView Answer on Stackoverflow
Solution 2 - CssmertyildiranView Answer on Stackoverflow
Solution 3 - CssPeanutsView Answer on Stackoverflow
Solution 4 - CssFatih HayrioğluView Answer on Stackoverflow
Solution 5 - Cssmck89View Answer on Stackoverflow
Solution 6 - CssDeminetixView Answer on Stackoverflow
Solution 7 - Cssajhit406View Answer on Stackoverflow
Solution 8 - CssSantiView Answer on Stackoverflow
Solution 9 - CssmheagerView Answer on Stackoverflow
Solution 10 - Cssuser1236048View Answer on Stackoverflow
Solution 11 - CssezzeView Answer on Stackoverflow
Solution 12 - Cssc_harmView Answer on Stackoverflow
Solution 13 - CssfdrvView Answer on Stackoverflow