Performance when combining specific page styles AND global style in the same page
Asked Answered
D

4

9

My main goal is to allow for the loading of several pages to be as fast as possible. For this I want to take advantage of both, the cache and one "special technique" that, as a fallback, relies on the standard cache.

Structure

On the backend I have the following structure. There's a main page in the public_html and several subpages, each with specific css rules different from each other. The creation of all the minimized files is done by a script, so no extra complexity there. For simplicity, let's assume that this is the structure, although it's more complex:

/public_html
  /index.php
  /style.css    ~50kb
  /min.css      ~100kb
  /subjects
    /index.php
    /style.css      ~20kb
    /min.css        ~10kb
  /books
    /index.php  
    /style.css      ~20kb
    /min.css        ~10kb
  ...

First request

So when the user enters first time on a subpage, they will receive this html code:

<!DOCTYPE html>
<html>
  <head>
    <link href="/subjects/min.css" rel="stylesheet" type="text/css">
  </head>
  <body>
    All the body here
    <link href="/min.css" rel="stylesheet" type="text/css">
  </body>

As you can see, the user loads all the css code needed for that page in the header, in a small file. Note that /subjects/min.css is MUCH smaller than /min.css which would make this first request to load faster. Then, after the full html and css has correctly loaded, the /min.css will start loading. This file contains all of the subpages style.

Note that it's appropriate to put the <link> within the <body> tag, and even if it didn't work, there's no problem since the page-specific style is already loaded. Why am I loading this here? Keep reading:

Following requests

For the second and subsequent requests on that session, the user will receive this html code:

<!DOCTYPE html>
<html>
  <head>
    <link href="/min.css" rel="stylesheet" type="text/css">
  </head>
  <body>
    All the body here
  </body>

The /min.css should be already cached from the first request. However, if for any reason it's not, it will load now the full minimized style, as in any normal website. This would be the fallback case.

Is this a valid scheme? Why haven't I seen anything like this before? Does it contain any logic error?

These are the main problems I can see, not strong enough in comparison to the benefits:

  • It adds some extra complexity to the code.
  • An extra request, after everything is already loaded, needs to be made. This would add a slight overhead on the server, however it's a static file.

Notes about the comments:

  1. The browser will make less requests. This is true, in this way the browser does one extra request. However, it's after loading the html and css, so this will not affect in a great manner the html.

  2. Cache. Yes, I'm doing my best to catch the file. A point could be made against cache of the <link> if it's inside the <body>, though, because I don't know if it behaves differently about the cache, I only assumed yes in the question.

Dao answered 12/2, 2014 at 20:13 Comment(10)
If you download a whole single css/js file minified with a long expire time, next request won load that file, and you dont need to reload minimal css parts.Agronomics
there are really two key aspects to this question, that basically invalidate it. The first is caching, you won't be sending the complete css files on each request, and the second is profiling. I would guess that your solution is neither for the client nor for the server more performant. Get yourself a decent web-profiler and measure timing instead of relying on the experiences of random strangers on a QA site :)Rebus
@AndreasGrapentin Yes, I would be sending the complete css file on each request, in the body for the first request and in the header in consecutive requests. Please read the full question. Can you name a profiler that would work for this specific situation then? One that accepts session cookies and sends them basically.Dao
@Agronomics I already know that, I just want the load to be faster than to have to load a full minimized css/js file.Dao
a full minimized file if has the cache headers setup will be served only once until it has expired, so technically you will be serving the file only once in their lifetimeAgronomics
1. using link tag in body tag may not work for older browser, it is not valid in HTML4 but fine in HTML5, for cross browser support it will have a concern 2. the subpage css need change when main css change, then for maintenance, updating main css need update all subpage css, for lots of page this will be painfulInner
I disagree regarding the benefits. Code maintenance might be an issue with this approach cause it is not very standard. It is kind of overkill for other team members (if any). Also this might bring some usefull info why to put style sheets in the head. I would suggest to simply use proper HTTP cache headers to accomplish best performancePhlebotomize
@ChrisLam I rephrased the question. For 1, it's already contemplated even for cross browser, it will just load as any normal page would. About 2, this is done automatically with a small script.Dao
@Phlebotomize the style.css would be the same, separated by parts. Please read the rephrased question as to see why I am puting some of the style at the end of the body.Dao
@FranciscoPresencia So until now have you done some profiling on this appoach, similar thing I have thought before, I think the main reason you do this may be faster css download for unblocking the html render, however css is allowed concurrently download and normally size is much smailler the javascript, so i just thinking is this worth to do. May be later i try to do a profiling myselfInner
A
5

Yes, what you are doing is perfectly valid and common

CSS is perhaps a bad example, but the same principle ( load the last one in via ajax btw )

Like say, images.

We are on page 1 of our website and we know 99.999% of the time our visitors are going to click to page 2, and we know that on page 2 we have some large images to serve, yes, then we may load them silently AFTER page 1 has loaded - getting ready, then the site 'feels' fast as they navigate. A common trick in mobile web applications/sites/

So yes:

It is the same principle for ANY type of file that you may want to 'pre cache' for subsequent requests.

  • Load the page
  • while the visitor is 'reading' the loaded page, pre fetch files/data that you expect they may request next. ( images, page 2 of result data, javascript, and css ). These are loaded via ajax as to not hold up the page 'onload' event firing - a key difference from your example

However, To answer your goal - allow for the loading of the pages to be as fast as possible

Doing this, or any kind of 'pre emptive loading' technique, is minimal to 'speed of delivery' if we are not serving static files from a static server, a cookieless domain , and ultimately a Content Delivery Network.


Achieving the goal of allowing for the loading of the pages to be as fast as possible, is the serving of static files differently from your dynamic content ( php rendered et all )

1) Create a subdomain for these resources ( css, js, images/media ) - static.yourdomain.com

2) Turn off cookies, headers and tune cache headers specifically for this sub domain.

3) Look into using a service like http://cdnify.com/ or www.akamai.com.

These are the performance and speed steps for serving static content. ( hope no suck eggs, just directly related the question and if anyone is unfamiliar with this )

The 'pre emptive loading' techniques are still great, but they are now more related to pre loading data for usability than they are for speed.


Edit/Update:

To clarify 'speed' and 'usability speed'.

  • Speed is judged by software often as when the page 'onload' event fires ( that is why it is important to load these 'pre emptive resources' via ajax.

  • Perceived speed ( usability ) is the how quickly a user can see and interact with the content ( even though the page load event may not have fired ).


Edit/update

In a few areas of the post and in the comments was mentioned the loading of these additional 'pre emptive' resources via javascript/ajax.

The reason is to not delay the page 'onload' event firing.

Many website test speed tools ( yslow, google .. ) use this 'onload' event to judge page speed.

Here we delay the page 'onload' event.

<body>

... page content 

<link rel="stylesheet" href="/nextpage.css"  />
</body>

Here we Load via javascript /some cases Ajax ( page data ) and do not preventing the page load event

<body>
.. page content

  <script>

    window.onload = function () {

       var style   = document.createElement( 'link' );
       style.rel   = 'stylesheet';
       style.type  = 'text/css';
       style.href  = '/nextpage.css';
       document.getElementsByTagName( 'head' )[0].appendChild( style );

   };

   </script>

( this, as a bonus, also gets around the compatibility problems with having a <link> tag within the <body> as discussed in your other threads )

Apex answered 16/2, 2014 at 10:48 Comment(12)
How are they more related for usability than for speed? Otherwise, can you put an example where the pre emptive loading technique is used? It seems similar to what I'm doing in my personal website, francisco.io. The main page loads and, meanwhile, the description of each project is loaded in the background, so when you click on any project the description is already loaded but the main page didn't take as long as it would if loaded at once [note it's under construction and many descriptions are still empty].Dao
The most common in relation to speed, would be 'page 2 of results'. We search and get page 1 or results, and in the background we 'pre emptively load page 2' - usability is closely related to speed I guess. What I am saying , is that what you are doing is fine/common, but there are better speed savings to be made by using a static domainApex
Another example of the pre emptive loading technique is the part where I talk about images. What you are doing with CSS is a 'pre emptive loading technique'Apex
Okay, my idea is to do it on top of the best practices already out there like cdn, except when they disagree directly (like loading everything upfront). Still, any source for the preventive loading for images? Everything I am finding is really old.Dao
If you look at Googles page speed insights, it recomends that you inline CSS ( the only CSS you need for that page ) - this is a form of what you are doing. And then to 'pre load' later ( again via ajax though ) is good.Apex
I've found this question that suggests the same as you're suggesting. I only have one question, why would you load it through ajax instead of at the end of the html body in my case? Note that the main min.css rules should not conflict with the specific subpage's rules.Dao
Hi Francisco, if we don't load them via ajax, we delay the page 'onload' event firing. This will stop the status bar 'done' message and give us slower 'page load speeds' from speed test sites ( yslow, google etc )Apex
There is an example of pre fetching resources via ajax and not holding up the page onload event here - phpied.com/preload-cssjavascript-without-executionApex
That was in the link I posted :P If you could add the relevant bits of the comments on your main answer, I'll accept it.Dao
@RobSedgwick Well you explain a lot of things that are perfectly right in your answer. And as you mentioned yourself, all this might belong to image and Javascript files, but certainly not to CSS files!. And imho there are also several issues ...! You'll never know, what the 'next page' a visitor goes to will be! So chances are high you are causing unnecessary traffic, which users with a data plan won't be happy with. Additionally making loading of a CSS file dependent on JS is at least "far from being ideal".Engadine
Sure thing @Netsurfer, I felt the question was more rhetorical about preloading any kind of static resource, agree that CSS being one of those resources is a 'bad example' - CSS files usually being light in filesize anyway as your great answer mentions.Apex
As for 'should never split up CSS files', well that depends on the job in hand. For larger web application it is common to have CSS files that are not related, but we still may like to 'pre fetch' . The most common is a streamlined login page. ( see o.v's post ) Using the time the user takes to 'login' by getting stuff loaded in the background for the main app. it's a nice touch.Apex
E
6

UPDATE:

Please mind that the answer which the questioner marked as accepted cannot be recommended -
don't ever do this!

Any kind of "pre-loading" of CSS files doesn't make any sense, as you should never split up your CSS into several files!

My original answer:

So what is your real question in the end?

In my humble opinion your doing it all wrong - sorry!

Usually an author intends to

  • give a site a consistent look/ appearance
  • keep the maintainability as easy as possible
  • avoid FOUC (flash of unstyled content)
  • minimize number of (HTTP) requests
  • support cache mechanism to reduce bandwidth/ data volume

just to mention some of the most important aspects.

All of them are disregarded by your approach.

As you are using the link element within the body element, I assume you are using HTML5. Because in other HTML versions this would be invalid.

But also in HTML5 I would not rely on this. Have a look at the 2 versions:

  1. http://www.w3.org/html/wg/drafts/html/master/document-metadata.html#the-link-element
  2. http://www.w3.org/html/wg/drafts/html/CR/document-metadata.html#the-link-element

Compare the section (at the top) "Contexts in which this element can be used:".

As the information from the CSS is most needed by the browser to render a page, it should be one of the first things loaded.

Have a look at the article:"How Browsers Work: Behind the scenes of modern web browsers" and especially at the section:"Rendering engines".

So loading another style sheet will force the browser to redo all the work, beside the additional HTTP request, which in particular on GSM connections may cause "trouble" because of the greater latency.

And if each page of your site really has such an amount of individual style rules then I would say it is a "design flaw".

One of the "design principles" is: As much as necessary - as little as possible!

Another (big) advantage of using just one style sheet is that it is cached by the browser after the first load. And as the CSS of a site normally doesn't change too often this is a great advantage which by far outweighs the disadvantage of some more KB to load on first page visit (btw independent of the entry/ landing page)!

Conclusion:
I really cannot recommend to use your approach!

Put all your styles (normalize, basic, media queries, print) in one single file which you load via <link> in the <head> of your document.

That's the best you can do.

Engadine answered 15/2, 2014 at 15:44 Comment(10)
I'm sorry, but I think in the original question I phrased many things just wrong. I rephrased the same question to make it more clear. I think the only point I'm missing is the minimize number of (HTTP) requests and maybe the FOUC, which I'm trying to completely understand how it applies for this. Although I agree with And if each page of your site really has such an amount of individual style rules then I would say it is a "design flaw", I think it's indeed needed in this case. The page has /subjects, /books, /slides, etc, each of them with a clear different style.Dao
@FranciscoPresencia And even after your update the answer stays the same. It looks like you try to re-invent the wheel ...! There is no better and faster way than to put all your styles in one single file. Keep it as small as possible and make sure that your server compresses the file (Content-Encoding:gzip) before delivery. As the browser's rendering engine is very fast in comparison to the data transfer, splitting your CSS to several files has imho only disadvantages!Engadine
You make the statement There is no better and faster way than to put all your styles in one single file when my question is, basically, is my method faster than to put all the styles in a single file? I'm making a point against what is commonly done, so just saying that I'm not doing it as it's commonly done without a reason behind it gives me little explanation. This is the flaw of these statements: minimize number of (HTTP) requests and give a site a consistent look/ appearance. They are generalizations that don't apply for my goal and question.Dao
@FranciscoPresencia "Your method" may be faster on the first (ever) visit on your site! After the first load it is certainly not! I thought I wrote this before. And also "speed" depends on so many different circumstances, all different for each and every user (e.g. type of connection). So the slower the connection of an user, the slower is your approach. And believe it or not, there is no "faster" way, than to have one single CSS file which is gzip'ed delivered by the server! All your approaches by splitting the CSS file to reduce the file size won't have the desired effect ...!Engadine
@FranciscoPresencia And the answer you accepted won't make a change to this facts. Handling your CSS files in such a manner (pre-loading, add link element to the body by JS etc.) will make things even worse ...! Why don't you concentrate on optimizing your CSS code instead? And normally a CSS file for a large website won't be greater in file size than one image. So imho you are trying to optimize in the wrong place.Engadine
@FranciscoPresencia And if you use the HTML5 application cache (which you certainly will do), then you won't make things better by splitting your CSS into dozens of separate files, as the whole cache must be reoloaded if one of its resources has changed.Engadine
I don't see how after the first load it will not be faster, since the main min.css will already be in the cache for the next loads... pre-loading is tangential to optimizing; they can both coexist and each brings a benefit in different ways. The point of the CSS size being smaller than the image is good and true, I'll also focus on optimizing images wherever I can. Also I had never heard of HTML5 application cache, I'll dig into that because it seems extremely useful.Dao
While I don't agree with your main answer, the comments contain a lot of useful information. It's a pity that I cannot split the bounty.Dao
@FranciscoPresencia When you say:"I don't see how after the first load it will not be faster, since the main min.css will already be in the cache for the next loads.", well that's mainly because if you only have one CSS file it will also be in the cache already and no seconfd or third CSS file needs to be loaded. And also remember that even if the file is cached the browser needs to make a request (at least for the '304 not modified' response of the server). So server response time and/or latency (on GSM) still matters. And GZIP compression is also more efficient on one large file!Engadine
Oh okay, now I see what you mean. The second request will only have 1 file. So the first request will be faster and the second one the same as with the traditional methods. How is that a disadvantage? About gzip, I didn't even think about it, although it seems like a micro-optimization, the same as pre-loading. I'll need to do some tests for this part.Dao
A
5

Yes, what you are doing is perfectly valid and common

CSS is perhaps a bad example, but the same principle ( load the last one in via ajax btw )

Like say, images.

We are on page 1 of our website and we know 99.999% of the time our visitors are going to click to page 2, and we know that on page 2 we have some large images to serve, yes, then we may load them silently AFTER page 1 has loaded - getting ready, then the site 'feels' fast as they navigate. A common trick in mobile web applications/sites/

So yes:

It is the same principle for ANY type of file that you may want to 'pre cache' for subsequent requests.

  • Load the page
  • while the visitor is 'reading' the loaded page, pre fetch files/data that you expect they may request next. ( images, page 2 of result data, javascript, and css ). These are loaded via ajax as to not hold up the page 'onload' event firing - a key difference from your example

However, To answer your goal - allow for the loading of the pages to be as fast as possible

Doing this, or any kind of 'pre emptive loading' technique, is minimal to 'speed of delivery' if we are not serving static files from a static server, a cookieless domain , and ultimately a Content Delivery Network.


Achieving the goal of allowing for the loading of the pages to be as fast as possible, is the serving of static files differently from your dynamic content ( php rendered et all )

1) Create a subdomain for these resources ( css, js, images/media ) - static.yourdomain.com

2) Turn off cookies, headers and tune cache headers specifically for this sub domain.

3) Look into using a service like http://cdnify.com/ or www.akamai.com.

These are the performance and speed steps for serving static content. ( hope no suck eggs, just directly related the question and if anyone is unfamiliar with this )

The 'pre emptive loading' techniques are still great, but they are now more related to pre loading data for usability than they are for speed.


Edit/Update:

To clarify 'speed' and 'usability speed'.

  • Speed is judged by software often as when the page 'onload' event fires ( that is why it is important to load these 'pre emptive resources' via ajax.

  • Perceived speed ( usability ) is the how quickly a user can see and interact with the content ( even though the page load event may not have fired ).


Edit/update

In a few areas of the post and in the comments was mentioned the loading of these additional 'pre emptive' resources via javascript/ajax.

The reason is to not delay the page 'onload' event firing.

Many website test speed tools ( yslow, google .. ) use this 'onload' event to judge page speed.

Here we delay the page 'onload' event.

<body>

... page content 

<link rel="stylesheet" href="/nextpage.css"  />
</body>

Here we Load via javascript /some cases Ajax ( page data ) and do not preventing the page load event

<body>
.. page content

  <script>

    window.onload = function () {

       var style   = document.createElement( 'link' );
       style.rel   = 'stylesheet';
       style.type  = 'text/css';
       style.href  = '/nextpage.css';
       document.getElementsByTagName( 'head' )[0].appendChild( style );

   };

   </script>

( this, as a bonus, also gets around the compatibility problems with having a <link> tag within the <body> as discussed in your other threads )

Apex answered 16/2, 2014 at 10:48 Comment(12)
How are they more related for usability than for speed? Otherwise, can you put an example where the pre emptive loading technique is used? It seems similar to what I'm doing in my personal website, francisco.io. The main page loads and, meanwhile, the description of each project is loaded in the background, so when you click on any project the description is already loaded but the main page didn't take as long as it would if loaded at once [note it's under construction and many descriptions are still empty].Dao
The most common in relation to speed, would be 'page 2 of results'. We search and get page 1 or results, and in the background we 'pre emptively load page 2' - usability is closely related to speed I guess. What I am saying , is that what you are doing is fine/common, but there are better speed savings to be made by using a static domainApex
Another example of the pre emptive loading technique is the part where I talk about images. What you are doing with CSS is a 'pre emptive loading technique'Apex
Okay, my idea is to do it on top of the best practices already out there like cdn, except when they disagree directly (like loading everything upfront). Still, any source for the preventive loading for images? Everything I am finding is really old.Dao
If you look at Googles page speed insights, it recomends that you inline CSS ( the only CSS you need for that page ) - this is a form of what you are doing. And then to 'pre load' later ( again via ajax though ) is good.Apex
I've found this question that suggests the same as you're suggesting. I only have one question, why would you load it through ajax instead of at the end of the html body in my case? Note that the main min.css rules should not conflict with the specific subpage's rules.Dao
Hi Francisco, if we don't load them via ajax, we delay the page 'onload' event firing. This will stop the status bar 'done' message and give us slower 'page load speeds' from speed test sites ( yslow, google etc )Apex
There is an example of pre fetching resources via ajax and not holding up the page onload event here - phpied.com/preload-cssjavascript-without-executionApex
That was in the link I posted :P If you could add the relevant bits of the comments on your main answer, I'll accept it.Dao
@RobSedgwick Well you explain a lot of things that are perfectly right in your answer. And as you mentioned yourself, all this might belong to image and Javascript files, but certainly not to CSS files!. And imho there are also several issues ...! You'll never know, what the 'next page' a visitor goes to will be! So chances are high you are causing unnecessary traffic, which users with a data plan won't be happy with. Additionally making loading of a CSS file dependent on JS is at least "far from being ideal".Engadine
Sure thing @Netsurfer, I felt the question was more rhetorical about preloading any kind of static resource, agree that CSS being one of those resources is a 'bad example' - CSS files usually being light in filesize anyway as your great answer mentions.Apex
As for 'should never split up CSS files', well that depends on the job in hand. For larger web application it is common to have CSS files that are not related, but we still may like to 'pre fetch' . The most common is a streamlined login page. ( see o.v's post ) Using the time the user takes to 'login' by getting stuff loaded in the background for the main app. it's a nice touch.Apex
K
3

Since min.css contains all styles properly minimized, just use that


Why ?

1.The browser will make less requests

2.The file will be cached after fetching for some 2 or three times by the browser. Tremendous decrease in page load time !

3.The browser doesn't have to go through the specific page's css, which in turns decreases the time needed for a page to render

4.Easy maintainability of code. If you want to update css, just prefix some query variable, so that browser fetches the updated css


I think , the above reasons are enough for you to use just the min.css

Also, don't forget to set a reallyyyyy long cache expiry date, if you would do as I've recomended

Edit: As OP didn't understand point 2, I'm gonna make myself and the point clear.

The browser will not cache the css file in it's first encounter, because it thinks : 'Hey, Let's not cache this immediately. What if it changes ? I will see to that, the same css is being reloaded atleast 2 times, so as to reap the benefit of caching'

There's no point in caching the css, when it is first loaded. Because if the browser does that, then there will be huge amount of cahce on the user's system. So browsers are clever enough to cache the files that are frquently loaded and unchanged.

Knell answered 15/2, 2014 at 16:7 Comment(1)
Please read the updated question, I tried to make it more clear although the question remains the same. I think it will explain clearly points 1 and 3. About 4, the code is the same on the back end no matter what, then a script fetches it and minimizes it, so it is easily maintainable. Can you explain the point 2, please? I didn't understand the sentence, it might have to do with me not being native in English, sorry.Dao
P
2

What you're describing is a pre-fetch/lazy-load pattern with resources loaded in anticipation of becoming relevant in the future - for instance, a basic login page with minimal styling that starts loading site css in the background.

This has been done before, among other things, in PageSpeed Module. In fact, it's more aggressive yet requires less development effort! A vanilla landing page (like a login screen) utilizing only a small subset of styles could take advantage of prioritize_critical_css that inlines relevant rules into the html and loads css at the bottom of the page! Unlike your original scenario where two consecutive requests have to be performed, the render-blocking effects of not having stylesheet in the head are being offset. This improvement is well-perceived by first-time visitors using mobile devices, who are subject to higher network latency and smaller number of simultaneous http requests allowed.

A natural progression of this would be to lazy-load sprites, webfonts and other static cacheable content. However, I'm inclined to speculate that the benefits of having well-structured separate css are probably superficial, and you would generally do well with minifying styles into one file. The difference in loading time between a 5 and a 50 kilobyte file is not tenfold, it's negligible, since website performance does not depend on bandwidth anymore. As a side note, you'll never have to worry about dependency management (i.e. remembering to include rules relevant to specific elements on your page), which is not easily automated for html+css and gets quite hairy for big projects.

If you focus on the cardinal rule of static resources - aggressive caching - and remember to fingerprint your assets so that deployments don't get messy, you're doing great! And if you address perceived performance with a well-placed throbber here and there...

Preterhuman answered 19/2, 2014 at 0:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.