1

Problem

I have made a Bootstrap 3.2.0 site with multiple different pages. Every different page has it's own, whole bodywide backgrond image. I have now gone the simplest route by making different CSS-file bodycssforthispage.css for every page. bodycssforthispage.css only contains the following code, and by then overwrites Bootstraps original body definitions:

html,body {
    height:100%;
    background-color: #333;
    background-image: url(../img/bg-image.jpg);
    background-repeat:no-repeat;
    background-size:cover;
    background-position:center;
    background-attachment: fixed;
}

Now what I want to do here, is to preload all other site related CSS-files, so that when I go for example from index.html to page1.html, all the are needed files (CSS-file for background and images) are already preloaded to browsers cache, and the transition to the next page is smooth. It is important to notice, that I want to preload the whole CSS-file(s) and it's contents.

Solution 1: preload all images and use different .css for each page

I could preload all images needed with JavaScript by placing this simple code to the bottom of my index page:

<script type="text/javascript">
if (document.images) {
    img1 = new Image();
    img1.src = "img/bg1.jpg";
    img2 = new Image();
    img2.src = "img/bg2.jpg";
}
</script>
</body>
</html>

and then just create bgforthisandthatpage.css for each different page, only containing:

html,body {
    height:100%;
    background-color: #777;
    background-image: url(../img/bg-imageforthispage.jpg);
    background-repeat:no-repeat;
    background-size:cover;
    background-position:center;
    background-attachment: fixed;
}

Problems using this way

This would be the simple solution, but it includes many many different .css-files. Preloading 5-10 CSS-files should be done at the bottom of the page so, that the page itself loads smoothly (just like in Bootstrap with many other scripts).

It is come to my knowledge (correct if I'm wrong) that preloading whole CSS-files (i.e via JavaScript) may cause cascade styles to overwrite each other, so that the page would then use the most bottom CSS-file(s) data (bg-image ect. in my case).

In my opinion preloading many different CSS-files just for the changing background image is not quite convenient.

Solution 2: give every html/body element it's own class with different bg-image

Giving each page it's own class like this:

<html class="contactpage-bg-image">

and then create own class for each page into the original css-file like this:

html.contactpage-bg-image {
    /* styling */
}

html.indexpage-bg-image {
    /* styling */
} 

Problems using this way

If images are big-sized and there are a lot of them, it impacts dramatically to the index.html loading time, because it will fist load all images mentioned in .css file (as you know, the code to the .css is located at the top of the page between and tags).

Questions

What is the best way to:

a) Change the background image for different pages using some funky preload function (note that bg-image has to be in the body, because some fadeloader.js stuff in my site), and;

b) Is there any better way to do this then by making thispagesbg-image.css file for every single site and;

c) Feel free to come up with your own ideas to do this!

Solution would prefered to be done compleatly in Javascript, jQuery or some mixature with css (or what ever suits to do this task most efficiently).

After 2 hours of comprehensice Googling, I only came up with nothing. I found this Pre-loading external files (CSS, JavaScript) for other pages, but I think that this loads everything before my page is loaded.

EDIT: Temporarely fix

I have now created class for each page's <html> on mypagesCustomCSS.css (and copying it as much as needed):

html.page1ClassH, html.page1ClassHere body {
    background-image:url(../img/bg-for-page1.jpg);
}

html.page2ClassHere, html.page2ClassHere body {
    background-image:url(../img/bg-for-page2.jpg);
}

and then I have placed following image preload JavaScript to the bottom of my index.html just before </body> tag:

<script>
$(window).on('load', function() { 
   if (document.images) {
    img1 = new Image();
    img1.src = "img/bg-for-page1.jpg";
    img2 = new Image();
    img2.src = "img/bg-for-page2.jpg";
}
});
</script>

This does the trick for now! As I mentioned earlier, I am using this page through iPhone 4 and slow 3G connection, so the preloading is vital.

I am still experiencing some problems with my site, as it lag's a lot. Perhaps I should resize those super-sized images and try again. Have a try at: http://www.kolumbus.fi/~g636221/jano/index.html

Community
  • 1
  • 1
Kasperi Koski
  • 55
  • 1
  • 2
  • 12

2 Answers2

2

Solution 2 looks good to me as you don't need to create multiple css files + will be cached on the first request. One clarification though, only the images for the css classes used on the page will be downloaded here.

So now, the only task remains is to pre-load resources for other pages user is about to browse. For this you can create a javascript file or jQuery code which downloads resources after the current page has been loaded completely.

jQuery File (Code)

var pages = ["class1", "class2", "class3"]; //Declare all pages here
window.onload = windowloaded();
function windowloaded()
{
    for(i=0; i < pages.length; i++)
     {
          $("div#preloader").append("<div class='" + pages[i] + "'></div>"); //This will load all other resources automatically as css classes are already present on the current page.
     }
}

HTML Code (Add to all pages, anywhere on page. This remains invisible and is responsible for pre loading resources for other pages.)

<div id="preloader"></div>

CSS Modification (Single CSS for all pages)

div#preloader { display : none; } 

Replace this :

html.contactpage-bg-image {
    /* styling */ 
}

with :

.contactpage-bg-image {
    /* styling */
}

removing html will make the class applicable for div which is used for preloading the image.

Ankit Singhania
  • 1,010
  • 9
  • 17
  • Refering to the bottom of your solution, can I use these classes with body tag? i.e ``??? BG-image class should NOT be inserted inside `
    ` class because it will mess some things with my page (tried that and doesn't fiy with my fadeloader jQuery script)
    – Kasperi Koski Aug 09 '14 at 18:47
  • Yes, that should work too. After adding `body` before the CSS selector, you also need to change jQuery code from `$("div#preloader").append("
    ");` to `$("div#preloader").append("");`
    – Ankit Singhania Aug 09 '14 at 19:03
  • This doesnt work, because the BG-image has to be sen inside `html,body {/*styles*/}` Now it only messes my BG-image, when I resize to smaller and scrol down. I think that the preloading code you provided doesnt fit. Check it out on www.kolumbus.fi/kadn/Janon%20pokeri/index.html – Kasperi Koski Aug 09 '14 at 19:53
  • Just modified the answer. Please replace the jQuery code as it was not working. Also you need to have the page body classes in the array there like `'redchip','kopteri'` there. And as you are not using `body` in the css selector `div` should work. – Ankit Singhania Aug 09 '14 at 20:11
  • I've putted the new jQuery code that you provided inside `css_preloader.js` file and saved. Looking from Chromes Dev.tools, it still isn't loading anything after page is loaded and the BG-image issue at smaller browser window-size still exists. Like I said, the background-image **has to be set inside** `html,body {/*styles*/}` css-tag. Or maybe it's just me doing something wrong. Just makes me wonder, that is it neccessery to have this kind of preloader, as I only need to preload big sized images. Should the preloader-code I described in "Solution 1" be enough for that? – Kasperi Koski Aug 09 '14 at 20:36
  • I think that the "gray area problem" exists, because i've setted bg-images in my css-code inside `.redchip` and `.kopteri` instead of `html,body`. Aaargh this is going to make me going nuts! At this point different `thispage.css` for every page sounds good. Then it would be easy to preload all pics... but still let's try to manage this by including all background-image codes inside my `defu.css` file... – Kasperi Koski Aug 09 '14 at 20:42
0

You could place all your separate CSS backgrounds into a single CSS file that is used across your site.

Give each background a class selector. Something like:

CSS

html.backgroundOne, html.backgroundOne body {
    /*styles*/
}
html.backgroundTwo, html.backgroundTwo body {
    /*styles*/
}

Then give each page a corresponding class on the opening <html>:

HTML

<html class="backgroundOne">

This way your CSS is already cached ready for use.

misterManSam
  • 24,303
  • 11
  • 69
  • 89
  • This was already in my mind, but takeing into account that my website is most likely used only by moblie technology (iPhones and that), the first-time loading time takes considerably long, because having 5-10 mb of pics in single CSS-file. Does the idea you described above load all the images from CSS-file, or only the ones that the current page needs? Then again, it wrecks the whole idea of preloading it it does not. There is one good preload script that I use, but it's only for pics... – Kasperi Koski Aug 09 '14 at 16:46
  • Is it a significant impact to pages loading time, if I put image preloader to the bottom of my page and then just change the bodybgimage.css for each page? Index.tml is using jQuery fadeloader and it gives somewhat 3-5 seconds precious loading time to the user. Also knowing, that no one clicks a link immediately gives some time to load next pages bg-images... – Kasperi Koski Aug 09 '14 at 16:51
  • With this method you are only loading ONE image on initial page load. The background image that matches the class: ``. After the page has loaded you can then pre-load the rest of your background images to speed up load times later on. – misterManSam Aug 09 '14 at 17:38
  • The one thing that you can optimise the most is the compression of your background image. You can take it a step further by loading an optimised image per screen resolution with `@media` queries. – misterManSam Aug 09 '14 at 17:41
  • Just to clarify, if there is for example 2500 different html.thispage classes in one sigle .css file with a total of 2500 different images, it really doesn't load all pics in the CSS, but instead only the one's that the page is using (stuff placed inside html/body tags with their classes) – Kasperi Koski Aug 09 '14 at 18:04
  • Correct, the CSS by itself does not do anything. In this example the images will only be downloaded and cached by the browser when the browser requests that specific `background-image` through the `class` in the HTML. – misterManSam Aug 09 '14 at 18:48
  • Oh BTW you writed ``. Did you mean ``? – Kasperi Koski Aug 09 '14 at 21:12
  • You can put a `class` on ``. [Here is a more in depth article](http://css-tricks.com/why-use-classes-or-ids-on-the-html-element/) if you want some more information :) You could also put the class on ``, whatever works best for your needs. – misterManSam Aug 09 '14 at 21:21