Delay loading your print CSS

June 17th, 2007. Tagged: CSS, performance

So you have two stylesheets on your page, like this:

<link type="text/css" rel="stylesheet" href="screen.css" 
      media="screen" />
<link type="text/css" rel="stylesheet" href="print.css" 
      media="print" />

The first one is used to render the page on screen, the other one is used for printing the page and print previewing it. Good.

The thing is, when it comes to performance, the browser won't render any part of the page, until all stylesheets are downloaded (fiddled with here). That includes, unfortunately, stylesheets not designed for the currently rendered media. In other words, the browser won't display your page, until the print stylesheet is also downloaded, although it's not used at all for displaying the page. That sucks and should really be addressed in future browser versions.

Test

I did a test page to check this, it's here - print.php. It includes two stylesheets, the first one intentionally sleep()s for 5 seconds, the second one - for 10 seconds.

The result is that in both Firefox and IE it takes 15 seconds for this page to be rendered. Here's the Firebug picture:

media-print.png

In Safari on Windows, it only took 10 seconds the first time around, as both stylesheets were downloaded simultaneously. Good. The bad is that after refresh, the first CSS was not even requested, I tried it a few times, actually sometimes I got the error "The error was: “unknown error” ((null):10053) ", but hey, this is the first release of the browser, it can't be perfect. Actually after I shut down Fiddler, which is what I used to monitor the HTTP traffic, the page was back to normal, so it's not clear who's to blame.

So?

Well, in order to increase rendering performance, all stylesheets not absolutely needed to initially render a page should be loaded after the page load, in the background. Once the user has a fast rendered page to interact with, you can load the additional CSS (and JavaScripts for that matter) in the background, using script and style DOM includes.

Update: From my comment bellow - a better option is to include the print css as part of the main css:
@media print {…}

Tell your friends about this post: Facebook, Twitter, Google+

33 Responses

  1. Interesting idea but wouldn’t this prevent non-javascript devices from using the print style sheet?

  2. @Scott: Perhaps you could include a noscript section…?

    You could also have an SWF loaded into an object section that writes Javascript to the page that pulls the print stylesheet into the page flow…

    :)

  3. This sounds a little backwards to me. I’m not sure we should add this kind of complexity to save a few k in downloads. Requiring Flash or JavaScript in order for the print CSS to work adds requirements to the user environment for what is probably minimal gains in performance.

    Can I ask how this idea was sparked? Did you have a real life scenario that made this worth investigating?

    Interesting, but I’m not sure it’s useful.

  4. I agree with Nathan. Usually the print stylesheet only takes a few extra bytes.

  5. Thanks for the constructive comments!

    @Nathan – There was no real-life scenario, just a quest for understanding how to build high-performance pages.

    @Michel – I guess the only thing you can do to make it more complicated is to have a javascript that makes an AJAX request to get contents for another script that generates the OBJECT tag on the fly :)

    @Scott – You’re right. The other option (and probably the best) is to include the print styles in the main CSS document with @media print {…}

    The question was not to save a few Kb, because you end up downloading the file anyway, only delayed in the background. The question was to decrease the number of HTTP requests during the initial load, since those are the most expensive. The thing in this case is that you have network latency and you never know how long it could take to download 1k css file. During this time users don’t see anything and the whole page seems slow to them. There were stats somewhere showing what percentage of the users will abandon the site for every second delay in loading. It’s just unfortunate to lose visitors when you page is fully loaded, but not rendered because the browser is waiting for one more css file which is not immediately needed.

  6. Interesting point. 1 kb may not be much on a per-page situation, but if you get a million visitors a month, that’s 1 GB of wasted bandwidth right there. Still not a huge amount for a large website, but nonetheless something worth investigating. Relying on js doesn’t seem great to me either, for the reasons already mentioned + the extra bandwidth + processing time required. Browsers should really be the ones offering a solution.

  7. It’s a creative idea, but it really hurts the accessibility of your page.

    If for some reason JS is unavailable, the browser won’t be able to use the print stylesheet. As a result you can only print the page including the navigation, banners etc…stuff you really don’t want to find back on your printed document.

  8. Thanks for the info, it’s fun to figure these things out even if there isn’t an “extreme” real-world need!
    But it’s an interesting read none-the-less… :-D

  9. hmmm, interesting discovery.

    Like everyone else has said, is this something really to fret about?
    The print style sheet should definitely be no bigger than a few bytes. After the first page load the styles should be cached by default reducing the load on the server. So even with this problem you are only talking about shaving off a few milliseconds on the initial load.

    I did a quick search on google about possibly importing the css through javascript but came across this informative article instead:
    http://www.sitepoint.com/blogs/2007/04/10/faster-page-loads-bundle-your-css-and-javascript/

  10. [...] Neste simples tutorial ensina como fazer. A técnica é simples. Ele simplesmente insere um script PHP no código CSS. Através da função sleep do PHP, browser pára a exibição do conteúdo, enquanto isso o css é carregado. Simples, não? [...]

  11. [...] Delay loading your print CSS [...]

  12. It doesn’t happend in Opera (I’m using Opera 9.21)

  13. In Opera the content is usually displayed earlier (even instantly if you want to). About 2 seconds after refresh the table is displayed unstyled, after 6 seconds the styles are applied, after about 11 seconds the page has finished loading.

    In the ‘preferences’ (ctrl-f12) under ‘advanced->browsing->loading’ you can set the time, when Opera should redraw the content. In my version it is set to ‘redraw after 1 second’. If I set it to 5 seconds, the table content appears first after about 5 seconds (unstyled of course) and gets its styling not a second later (because of your delay).

  14. I agree with Peter that browsers should not grab the print style sheet until the user tries to print or does a print preview, then it should grab it and cache it.

  15. @Peter
    Yeah, it would be great if the browsers did not get the print css until someone prints. You might put the print style on your site, not because many people print, but because it saves a few people ink.

  16. Actually, didn’t everyone miss the obvious solution? Simply set up a hidden frame to load the print-only version of the CSS file. Maybe even an iframe at the very bottom would work, and style it to not display or even be visible. Since the main content will load simultaneously with the frame it should all work just fine. Haven’t tried it cuz I don’t need that, but I bet it will be good. :)

  17. [...] You could think that the browser only loads the one stylesheet that matches the media it’s currently showing. Not true. All stylesheets, no matter what media they are tied to, are loaded at startup. [...]

  18. [...] phpied.com » Blog Archive » Delay loading your print CSS (tags: css performance development) [...]

  19. [...] You could think that the browser only loads the one stylesheet that matches the media it’s currently showing. Not true. All stylesheets, no matter what media they are tied to, are loaded at startup. [...]

  20. [...] Blog Archieve [...]

  21. [...] August 20, 2007 at 9:13 am · Filed under CSS, Javascript ·Tagged CSS, Javascript Примечание: ниже находится перевод двух близких статей (“Delay loading your print CSS” и “JS includes — the saga continues…”) по оптимизации загрузки страницы при наличии нескольких файлов стилей или скриптов. [...]

  22. Actually if you had a browser download the print stylesheet when a print was requested, this would impact people who download content and then go offline. Sounds strange but I do it all the time when away from a fixed connection (ie. I get a few pages on tabs and read later, offline). I guess the ideal browser behaviour would be to get the print css after everything else and cache it.

  23. well… i visit your website first time and found this site very usefull and intresting !

    well… you guys doing nice work and i just want to say that keep rocking and keep it up !!!!

    Regards
    Alishba

  24. Thanks for this information there is a print style sheet and sleep() function . The second line code is for printing the page.

  25. [...] Delay loading your print CSS Delay loading your print CSS [...]

  26. [...] also: Delay loading your print css – Stoyan [...]

  27. Is this the same in all web browsers ?

  28. [...] tweet had me revise a 5 year old experiment on how print CSS affects page loading, especially in the light of mobile [...]

  29. [...] you should use "@media print" within your unified stylesheet because, as Stoyan Stefanov has pointed out, browsers will always download all stylesheets no matter the [...]

  30. [...] you should use @media print within your unified stylesheet because, as Stoyan Stefanov has pointed out, browsers will always download all stylesheets no matter the [...]

  31. [...] page load times of a website by improving front end code performance. Spotting an opportunity to eliminate a HTTP request, I moved the print styles from a separate print stylesheet into the main CSS file and wrapped them [...]

  32. i have tested your print.php and it seams that chrome and safari have the
    content on the screen at the 5s. Whilest Firefox had the content on the screen at the 10s mark .

    safari 6.0.5: DOMContentLoaded: 7; onload: 15541
    chrome 30.0.1599.69: DOMContentLoaded: 1; onload: 13543
    firefox 24.0: DOMContentLoaded: 23; onload: 13705

  33. Wow, incredible blog layout! How long have you been blogging for?
    you made blogging look easy. The overall look of your site is wonderful, as well as the
    content!

Leave a Reply