don’t use @import

April 9, 2009 12:32 am | 90 Comments

In Chapter 5 of High Performance Web Sites, I briefly mention that @import has a negative impact on web page performance. I dug into this deeper for my talk at Web 2.0 Expo, creating several test pages and HTTP waterfall charts, all shown below. The bottomline is: use LINK instead of @import if you want stylesheets to download in parallel resulting in a faster page.

LINK vs. @import

There are two ways to include a stylesheet in your web page. You can use the LINK tag:

<link rel='stylesheet' href='a.css'>

Or you can use the @import rule:

<style>
@import url('a.css');
</style>

I prefer using LINK for simplicity—you have to remember to put @import at the top of the style block or else it won’t work. It turns out that avoiding @import is better for performance, too.

@import @import

I’m going to walk through the different ways LINK and @import can be used. In these examples, there are two stylesheets: a.css and b.css. Each stylesheet is configured to take two seconds to download to make it easier to see the performance impact. The first example uses @import to pull in these two stylesheets. In this example, called @import @import, the HTML document contains the following style block:

<style>
@import url('a.css');
@import url('b.css');
</style>

If you always use @import in this way, there are no performance problems, although we’ll see below it could result in JavaScript errors due to race conditions. The two stylesheets are downloaded in parallel, as shown in Figure 1. (The first tiny request is the HTML document.) The problems arise when @import is embedded in other stylesheets or is used in combination with LINK.

Figure 1

Figure 1. always using @import is okay

LINK @import

The LINK @import example uses LINK for a.css, and @import for b.css:

<link rel='stylesheet' type='text/css' href='a.css'>
<style>
@import url('b.css');
</style>

In IE (tested on 6, 7, and 8), this causes the stylesheets to be downloaded sequentially, as shown in Figure 2. Downloading resources in parallel is key to a faster page. As shown here, this behavior in IE causes the page to take a longer time to finish.

Figure 2. link mixed with @import breaks parallel downloads in IE

Figure 2. link mixed with @import breaks parallel downloads in IE

LINK with @import

In the LINK with @import example, a.css is inserted using LINK, and a.css has an @import rule to pull in b.css:

in the HTML document:
<link rel='stylesheet' type='text/css' href='a.css'>
in a.css:
@import url('b.css');

This pattern also prevents the stylesheets from loading in parallel, but this time it happens on all browsers. When we stop and think about it, we shouldn’t be too surprised. The browser has to download a.css and parse it. At that point, the browser sees the @import rule and starts to fetch b.css.

using @import from within a LINKed stylesheet breaks parallel downloads in all browsers

Figure 3. using @import from within a LINKed stylesheet breaks parallel downloads in all browsers

LINK blocks @import

A slight variation on the previous example with surprising results in IE: LINK is used for a.css and for a new stylesheet called proxy.css. proxy.css is configured to return immediately; it contains an @import rule for b.css.

in the HTML document:
<link rel='stylesheet' type='text/css' href='a.css'>
<link rel='stylesheet' type='text/css' href='proxy.css'>
in proxy.css:
@import url('b.css');

The results of this example in IE, LINK blocks @import, are shown in Figure 4. The first request is the HTML document. The second request is a.css (two seconds). The third (tiny) request is proxy.css. The fourth request is b.css (two seconds). Surprisingly, IE won’t start downloading b.css until a.css finishes. In all other browsers, this blocking issue doesn’t occur, resulting in a faster page as shown in Figure 5.

Figure 4. LINK blocks @import embedded in other stylesheets in IE

Figure 4. LINK blocks @import embedded in other stylesheets in IE

Figure 5. LINK doesnt block @import embedded stylesheets in browsers other than IE

Figure 5. LINK doesn't block @import embedded stylesheets in browsers other than IE

many @imports

The many @imports example shows that using @import in IE causes resources to be downloaded in a different order than specified. This example has six stylesheets (each takes two seconds to download) followed by a script (a four second download).

<style>
@import url('a.css');
@import url('b.css');
@import url('c.css');
@import url('d.css');
@import url('e.css');
@import url('f.css');
</style>
<script src='one.js' type='text/javascript'></script>

Looking at Figure 6, the longest bar is the four second script. Even though it was listed last, it gets downloaded first in IE. If the script contains code that depends on the styles applied from the stylesheets (a la getElementsByClassName, etc.), then unexpected results may occur because the script is loaded before the stylesheets, despite the developer listing it last.

Figure 6. @import causes resources to be downloaded out-of-order in IE

Figure 6. @import causes resources to be downloaded out-of-order in IE

LINK LINK

It’s simpler and safer to use LINK to pull in stylesheets:

<link rel='stylesheet' type='text/css' href='a.css'>
<link rel='stylesheet' type='text/css' href='b.css'>

Using LINK ensures that stylesheets will be downloaded in parallel across all browsers. The LINK LINK example demonstrates this, as shown in Figure 7. Using LINK also guarantees resources are downloaded in the order specified by the developer.

Figure 7. using link ensures parallel downloads across all browsers

Figure 7. using link ensures parallel downloads across all browsers

These issues need to be addressed in IE. It’s especially bad that resources can end up getting downloaded in a different order. All browsers should implement a small lookahead when downloading stylesheets to extract any @import rules and start those downloads immediately. Until browsers make these changes, I recommend avoiding @import and instead using LINK for inserting stylesheets.

Update: April 10, 2009 1:07 PM

Based on questions from the comments, I added two more tests: LINK with @imports and Many LINKs. Each of these insert four stylesheets into the HTML document. LINK with @imports uses LINK to load proxy.css; proxy.css then uses @import to load the four stylesheets. Many LINKs has four LINK tags in the HTML document to pull in the four stylesheets (my recommended approach). The HTTP waterfall charts are shown in Figure 8 and Figure 9.

Figure 8. LINK with @imports

Figure 8. LINK with @imports

Figure 9. Many LINKs

Figure 9. Many LINKs

Looking at LINK with @imports, the first problem is that the four stylesheets don’t start downloading until after proxy.css returns. This happens in all browsers. On the other hand, Many LINKs starts downloading the stylesheets immediately.

The second problem is that IE changes the download order. I added a 10 second script (the really long bar) at the very bottom of the page. In all other browsers, the @import stylesheets (from proxy.css) get downloaded first, and the script is last, exactly the order specified. In IE, however, the script gets inserted before the @import stylesheets, as shown by LINK with @imports in Figure 8. This causes the stylesheets to take longer to download since the long script is using up one of only two connections available in IE 6&7. Since IE won’t render anything in the page until all stylesheets are downloaded, using @import in this way causes the page to be blank for 12 seconds. Using LINK instead of @import preserves the load order, as shown by Many LINKs in Figure 9. Thus, the page renders in 4 seconds.

The load times of these resources are exaggerated to make it easy to see what’s happening. But for people with slow connections, especially those in some of the world’s emerging markets, these response times may not be that far from reality. The takeaways are:

  • Using @import within a stylesheet adds one more roundtrip to the overall download time of the page.
  • Using @import in IE causes the download order to be altered. This may cause stylesheets to take longer to download, which hinders progress rendering making the page feel slower.

90 Responses to don’t use @import

  1. Thanks for posting this! I’ve been in favor of link over @import for a while. Now there’s an article from an authoritative source to back up usage of link.

  2. irregardless of the performance considerations of import/link usage. it’s my belief that @import best usage is as a means of overriding existing styles logically in an existing framework or application.

    Take for instance these directions: http://www.redmine.org/wiki/redmine/HowTo_create_a_custom_Redmine_theme

    other CMS’s such as Drupal (drupal.org) simply [link] all css sheets needed from all modules in a page.

    my only point that i think i’m trying to make is that i agree towards the usage of [link] tags vs @import directives for all normal cases — unless its towards a means of CSS overrides and the underlying framework is looking for a single file called application.css (as Ruby on Rails does, which Redmine is developed with).

    thank you for the informative article.

  3. Nice catch Steve, very informative.

    @david: drupal can concatenate and minify all css files (recommended for production environment). I think this is the good way to serve your style sheets and javascript files. You can easily implement your own build process to do this via eg. YUI compressor or other tools.

  4. Thanks for this concise discussion Steve.

    I’d like to add that I’ve also run into a potential bug in IE8 production code where the browser doesn’t reflow the page/apply styles when a slowly downloaded CSS file is included via @import.

    Changing to ‘link’ fixes the issue.

  5. Thanks for this information and the tests. It is always a good idea to improve performance on our web sites.

    Linked from “Weterede!”

  6. Very good article! I’ve always wondered this myself, because I found some other issues with @import in Internet Explorer as well. I was also glad to see that you tested 6, 7, and 8, and not just 7 like lots of sites seem to do now.

    With the theme of @import and IE going on, I’d also like to share this article I wrote a while back on limitations it has with @import as well. http://tinyurl.com/d4uvgr

    Again, thanks for the excellent article! :-)

  7. I posted this on the Amazon blog version of this post, but it makes more sense to reply direct to the original source:

    “If the script contains code that depends on the styles applied from the stylesheets (a la getElementsByClassName, etc.), then unexpected results may occur…”

    You sound like an alarmist. #1 The script would still work just fine because “getElementsByClassName” is looking at HTML not CSS so the script would still work even if no CSS is loaded. #2 If everything is located in the of the document, what difference does it makes as to order of CSS/JavaScript? Everything has to be loaded before the rest of the page renders for the user.

  8. Finally, I have something to show my co-workers when I make my argument – again.

    Thanks for the details on this. Much appreciated!

  9. @david g: The Redmine theme example still works without using @import. Just use two LINKs – one for the default Redmine stylesheet, followed by one for your custom stylesheet. The CSS works as desired, and the page loads faster.

    @Russell: I see your point. Classname is a bad example. A better example is when the script is looking at style properties. If the script assumes the CSS has been applied, and iterates over DOM elements looking for a specific style attribute, it won’t find it, and the results are unexpected.

  10. All right, i won’t use it anymore.

  11. I’ve never really used @import & this is more reason I won’t be using it. Very well shown. Thanks for clearing the performance question for me. :)

  12. What is your test tool for IE???

  13. Steve, all examples that you use in your post make no sense.
    What I’m trying to say is I have never seen somebody using the link and @import at the same time. And I’ve seen many source codes in my life. That is not like everyday situation, more like an exeption.
    Why would anybody do such a thing?

    Next, you didnt give an example of the only way I used to use @import, and many other people that I know. And that is:

    @import url(‘a.css’);

    and ONLY that, no link and no combination of them. I put all my css rules in one css file.
    IF there are many lines of code, and if it makes sense, then I broke it into several other CSS files.
    From a.css I call other files with @import.

  14. How about linking to a one proxy.css, and @importing from there? The @imports download in parallel in all browsers, right?

    That way we would only have one in our , seems cleaner.

  15. That way we would only have one link-tag in our head, seems cleaner.

  16. Did you test the setup Antti is talking about? I’ve seen sites use a single link-tag to load a stylesheet that then uses multiple @imports for different stylesheets. How do stylesheets load in this condition–in parallel or sequentially?

  17. Not sure if this has already been said, but you left out a key example.

    If you only have one tag, and it contains nothing but @import rules, the CSS files are downloaded in parallel as soon as the single ‘d CSS file is downloaded, at least as far as I can tell.

    Can you update your post with this test? Thanks!

  18. My comment lost its markup, let’s try this:

    Not sure if this has already been said, but you left out a key example.

    If you only have one <link$gt; tag, and it contains nothing but @import rules, the CSS files are downloaded in parallel as soon as the single <link$gt;‘d CSS file is downloaded, at least as far as I can tell.

    Can you update your post with this test? Thanks!

  19. @well: I use HttpWatch to generate these waterfall charts. It costs money. You could try AOL Pagetest and IBM Page Detailer – both work in IE and are free, but they have fewer features.

    @webdizajn: More sites than you might believe mix LINK and @import: wordpress.com, nytimes.com, about.com, and adobe.com to name a few. It’s true that if you only have one stylesheet, using @import is the same as LINK. But if you have more than one stylesheet, loading them with multiple @import rules within another stylesheet can lead to blocking in the same way as the (newly added) Many Links example demonstrates.

    @Antti, DaveM, and Josh: I just updated the post with the LINK with @imports example to show how using @import from within a LINKed stylesheet adds one more roundtrip to the overall page load time, and may hinder progressive rendering.

  20. Thanks for posting this with clean examples Steve.

  21. @import may load everything succinctly, ie all-in-one heap, but causes most browsers to pause at least 2 second before each download

  22. Thank you very much for the updated tests!

  23. Although I never use the @import statement, now i’d not use them either. Thanks for the benchmarks and for such an effort to bring this issue to light.

    One Similar Discovery i made that if we don’t specify the content-type in meta, the page rendering takes longer at least in Firefox. If we specifically give utf or ISO, it’s faster. I’ve taken number of readings in firebug and yslow and got this information.

  24. How did you get results for IE? What instrument did you use to check perfomance?

  25. Hi there Steve.

    You raise some interesting issues here. How would you tackle the accessibility issues that your methods create? If @import was not required for this purpose I would drop all styling rules into one (statically or dynamically) arranged and compressed file for maximum efficiency. As far as I know this is not possible whilst remaining accessible and DRY. If you have discovered the magic bullet I would love to hear about it!

  26. Good article. I’ve noticed some slight delays and bugs when using @import myself previously but have never taken the time to investigate it further.

    The import issue is certainly noticeable when using js-libs that correlates to specific style properties just as you say. It’s nice to finally read the WHY and not just doing it because it seem to work better without @import. :)

  27. Nifty charts!

    It looks like, as long as you don’t use @import from an external .css file, and you don’t care about what IE might do with your webpage, then @import is OK to use. Is that correct?

  28. The client could get better performance by changing IE’s MaxConnectionPerServer, which defaults to 2. Instructions here: http://l370.blogspot.com/2007/01/internet-explorer-max-connections.html

  29. Thank you, Steve! I knew of some of these issues, but having all of these use cases organized and visualized is extremely helpful, useful, and practical. Keep up the good work!

  30. That’s a new motivation for not using @import. We never use it when developing something, and now, we’ll never use it. Thank you Steve.

  31. hi,

    GREAT post – thanks for that!

    Is it possible that alternate stylesheets are always loaded sequential in IE – even if no @imports are there?

    and that @import only influences the stylesheets following the @import-statement, i.e. if there are s first and some @import’s in the end, there’s no problem?

    again – thanks a lot!

  32. Stylesheets load in parallel in all major browsers (except Firefox 2). Here’s an example ( http://stevesouders.com/cuzillion/?c0=hc1hfff2_0&c1=hc1hfff2_0) with two stylesheets that each take two seconds to load. Notice the overall page load time is 2 seconds, thus showing they loaded in parallel.

    The “LINK @import” section above shows that using both causes blocking in IE.

  33. Thank you for the post, very interesting! But the true lesson here is… don’t use IE =D

  34. Wow! I am in the habit of separating my css into many files each with specific purpose, sometimes up to 10 files. All using @import from a LINK “proxy”.css

    My site was feeling slower than it should have. After changing them all to LINK, the difference was DRAMATIC!

    Not as “pretty” in the source code, but performance trumps all.

  35. It seems that most of this affects IE only. I typically use link, because it is easier to track, and, as I have read before slower.
    But this analysis of the link mixed with @imports is very interesting.
    By now, I’m sure the amount of bugs in IE far outweighs the features…

  36. @John
    I have to agree with that, don’t use IE 8-) However, I did find the theorem very intriguing.

  37. Steve,

    I’ve also heard that when using @import, browsers may not cache the css files, unlike with a . But I haven’t been able to verify this. Are you aware if it actually matters from a caching perspective? If so, it might be another reason to avoid @import.

  38. @Murray: I haven’t heard that and it doesn’t happen in my tests.

  39. Steve, I’m testing your example LINK LINK in IE6 and what can I see:

    Are you shure you not wrong with “Using LINK ensures that stylesheets will be downloaded in parallel across all browsers”?

  40. Sorry, dropped my proofpic

  41. @Vadim: Yes, I’m sure it works that way in IE6. The most likely explanation for what you’re experiencing is that you have an IE plugin that blocks stylesheets from loading in parallel. These types of plugins are using the Async Pluggable Protocol. Examples include the RealPlayer uploader, Sophos, and many others. Try disabling all your plugins. If you still have problems, send me an email via my contact page.

  42. Steve, you are right.
    http://www.debugbar.com — this plugin blocks stylesheets from loading in parallel

    Thank you for your investigations!

  43. This article is only for IE 6+ users. The tag is for CSS1 which old browsers can understand. If you use CSS2/CSS3 such as shorthand property, you have to use @import to exclude the old browsers. Otherwise the old browsers do not understand shorthand and will mess up the layout or cause error.

    If you do not mix LINK and @import, it does not hurt. Also, The tag should have a type attribute with the MIME type “text/css” attribute for fast load. Always add “/” after url for quicker load.

    Anyway, the CSS files load much faster than the images so not a big deal.

  44. I use multiple @imports which, as you say, do not get penalised unless followed by a script. If you are following best practise of placing your script file/s at the bottom of the page, thus avoiding the need to use window onload and on DOM ready type events because the DOM is ready at this stage, does this still lead to the script blocking the @import downloads?

  45. @Willabee: There are so many disadvantages to using @import, we shouldn’t focus on finding situations where they can be used without triggering problems. Using LINK instead of @import avoids the potential pitfalls. Unless there’s a benefit, use LINK instead of @import.

  46. @Steve: That does not answer my question. I use @import to filter out older browsers to give them a fully functional, accessible linear layout. Do you have a solution, without JavaScript, that can do this for me if I convert to using Link.

    I would like to use Link because of alternative style sheets but I feel it is more important to have every user-agent fully accessible to my sites.

    I believe the answer to my question is that using multiple @imports in my header section, followed by the rendering of my semantic XHTML, producing the DOM that will inherit the CSS rules from my @imports, and finally, just before the closing body tag, my JavaScript libraries load, followed by my initialisation script, without the need of DOM ready detection, and I am good to go without blocking.

    I am also utilising resource domains; js.my.com, css.my.com and img.my.com for my global resources to help with the two connection limitation.

    If you are not happy to test this for me, what tools do I need so that I can test myself.

    Thank you for your time and much appreciated.

  47. Hi,
    Was wondering if you can help. When I view the page source on my website the external files are linked!!! Dont know why but I certainly dont want them to be linked so others can view. any advise on how to get rid of the links?

  48. @child attitude: All of the stylesheets are delayed by the amount of time it takes to fetch proxy.css. It’s better to just use the LINK tag, and not make your users suffer this extra delay.

  49. OMG! Does someone still uses @import? Cleaner CSS code is better & and it’s a way to avoid @import.

  50. so what are the benefits then?
    I guess its browser issue not the syntax issue.

  51. We have also started to change our @import > Link, because based on our test link really load faster.

  52. Stylesheets Not Loading? 31 Reasons to Hate Internet Explorer

    http://john.albin.net/css/ie-stylesheets-not-loading

  53. not loading on ie :/

  54. A fantastic free tool instead of HttpWatch is http://fiddlertool.com – it is a proxy for recording all activity, but it also does waterfall charts (amongst other great features!).

  55. A while ago I ran tests on link vs import and came to the conclusion that IEv6 treats link in the same way as script. That is it prevented further parallel downloads until completion.
    I therefore concluded, perhaps true for only that specific case, using import was a more efficient solution.
    Reading the above article and it’s conclusion doesn’t appear to countermand that decision.
    To conclude: Nothing beats real world testing.

  56. @mike foskett: LINK tags by themselves don’t block downloads. You probably had a SCRIPT tag after the LINK tag – that will cause problems. Feel free to post a URL to your tests.

  57. I created a dynamic CSS library that will let you @include CSS files on the server instead of @import on the client. It also compresses and caches for performance. It’s a free download at http://www.coolphptools.com/dynamic_css

  58. @import is basic dependency management for big projects

    U can use some build script for production, which internalize your @imports

  59. Does the potential Javascript race condition adversely affect the page in any way if its code is designed to only run once the onLoad event is triggered?

  60. @ridgerunner: JS running after the load event will avoid any race condition. Also, even if IE8 downloads the script first, it holds off on executing it until after all the stylesheets are done, thus avoiding the race condition. I haven’t tested IE6&7. Use this Cuzillion test page and tell me what you see on other browsers. If the script execution time is after 2000ms, then the race condition is a non-issue.

    But this out-of-order is still a problem worth avoiding. I modified the many @imports test to put an image last. Because it gets downloaded and rendered first, there’s a flash-of-unstyled-content once the stylesheets arrive – something most (all?) developers wouldn’t have expected.

  61. @Steve

    Allthough forgotten today, it has been known for 9 years that IE’s rendering issues related to @import-inside-the-style-element, can easily be worked around:

    http://www.bluerobot.com/web/css/fouc.asp/

  62. duh.. should use “$amp;gt;” for “>”.

    Thanks for the article.
    There are some things that I am still curious about:

    1) If I am forced to have more than 31 stylesheets (typical for a Drupal test environment, where I don’t want to enable aggregation), and I want the site to work in IE, should I rather use all @import (with not more than 31 of them in one <style> tag), or a mix of <link> and @import? Remember, all <link> will break the layout in IE and is not an option.

    2) Does @import have any performance implications on non-IE browsers?

  63. @donquixote: 1) It would be better to work on a way to not have 31 stylesheets in Drupal. Regardless, I don’t have best practices for a page like that. 2) There are multiple issues that affect all browsers. Search above for “all browsers” to see the specific issues.

  64. hi,
    ySlow and google pagespeed downgrade the rate if you have used @import.

    Thanks

  65. We have also started to change our @import > Link, because based on our test link really load faster.

  66. I tried both, but it`s better and faster to use link then @import

  67. Just being curious…have you tried this out in IE9 yet? I would think with all the performance improvements that they have fixed this problem?

  68. @Ncage: IE9 behaves the same as IE8.

  69. yea you are right, but when we use @import our page is loading faster.. am I doing something wrong?

  70. There is a simple concluusion to what happens if You want to download externla ressources in parallel. One point is that there ist limited number of request that run parallel. Even if there is no browser limitation on that maybe the server has one. Another point is, that for each download a single request is done with all its overhead regarding IO.

    So maybe another appoach might be to concatenate the ressources on the server side (where You can easily manage the dependencies), pack them and deliver them in one respones to one request to client. This works fine for all server side progarmming languages.

  71. I’ve been working on an OSS project https://github.com/mwrock/RequestReduce that among other things, combines and minifies css for .net web apps. One feature I implemented fairly recently is the ability to recursively automatically expand @imports. This has proven to takes the bite out of @import perf yet allows web dev/designers to keep them.

  72. This article was pointed out to me a while ago by a CSS guru and as a result Miser (http://sourceforge.net/projects/miser/) merges all @imports to mitigate this. Great article.

    Have you also looked at web fonts? (eg *.eot). They also force sequential downloads and unfortunately are becoming more and more prevalent.

  73. @ShaunR: I’ve written 3 blog posts about fonts. Here’s a good place to start: Frontend SPOF.

  74. Thanks to your post and I fixed another reject from my GTmatrix tasks :)

  75. @import provides inheritance in large scale projects and moreover allows you to internally manage dependencies (instead of managing them within each page.) I think the use case there is probably different than for what you are talking about, but I felt compelled to argue that internal dependency mgmt does have its place.

    A typical use case might be a site.css to style all pages, a userprefs.css to style pages that have to do with user preferences, then an addressinfo.css specifically for addressinfo.htm.

    One link tag on addressinfo.htm would get addressinfo.css. The rest of the sheets are managed independently by the import statements internally, where @import userprefs.css, would automatically @import site.css… and so on, making dependency mgmt/maintenance far easier and opening up the world of inheritance to stylesheets natively.

  76. Thanks very much for the article Steve. It’s pretty interesting that link blocks import in IE when the links are declared first. One thing I’m curious about though, if you specify one or more @imports in a style block, and then specify one or more links afterwards, would the downloading links still block the imports, or would the imports go down first? I mean without adding scripts to complicate matters. Ok they wouldn’t go down in parallel would they, but if you just used link for legacy browsers that wouldn’t matter so much. And maybe the imports would all go down in parallel before the links got going? Or have you answered that already in this article and I’m just being a bit thick? Cheers!

  77. @Shanimal: I agree that @import helps with dependency management. If that’s important to the dev team I recommend a build process or other tool to flatten the @import dependencies in production. (Mod_pagespeed just announced flattening of @imports.) Whenever there’s a tradeoff of making it better for developers or better for users, I feel programmers should favor their users, esp. if the pareto optimal solution is possible with infrastructure enhancements.

    @tansel: Yes, if the JS is delayed until after all the CSS is loaded then there is no race condition.

    @Catspaw: Cuzillion is a great tool to be familiar with for answering questions like this. Here’s a test page that has an inline @import followed by a link’ed stylesheet. In Chrome 18 & Firefox 11 they load in parallel.

  78. Ok Steve, I’ve tested a simple setup in your Cuzillion (dead nice!): one import followed by two links (each 4 secs so we see what’s going on). In a windows environment in IE6, 7 and 8, Opera, and Safari, they all appear to load in parallel (just over 5 secs in total). But of course if you use scripts as well you are still likely to mess it up with white screens or FOUS. So maybe sticking with many links is still the best bet. Does IE8 still limit concurrent downloads to 2 files by the way, and how about IE9?

  79. Steve ignore my last point, can’t apply if all files were downloaded concurrently – duh! (unless I’ve done something wrong). I’ve expanded the test to include 3 imports (4 secs each) followed by 2 links (4 secs each) and get some interesting results. In IE6-8 you get a wide variation in download time, mostly around 12 secs but can be as little as 9 but once actually took 18secs. Opera responded similarly (although didn’t get the upper value repeated). Safari had the best result, just over 5 secs! While FF came in at a respectable 7 secs or so. Looks like this has finally hit the last nail in for me, using multi imports followed by links obviously causes all sorts of stuff to go haywire.

  80. I have one problem with the link-solution: IE has a limit on how many links you can have in a page, 31 to be precise. In our platform we have already reached that number. IE does not have a limit on how many imports you can do.
    The problem with the links is that it’s not always obvious which css file IE decides not to load. We e.g. use Telerik controls, which automagically create their own links through javascript. When that happens, it could be that one of our own stylesheets is dropped out of the load. Nasty!

  81. Thanks for the analysis Steve!

    One benefit to doing something like…

    all.css:
    @import url(home.css);
    @import url(resets.css);
    etc

    … is in development they are all uncompressed and not combined, but in production you can dynamically combine all the stylesheets.

    For instance, with Stylus, one can have a main stylesheet with
    @import “resets”;
    @import “home”;

    And at runtime they are all combined. You can also precombine them in node.js.

    Thanks again Steve!

  82. @bilgi: @import has no effect on caching.

  83. Hey Steve

    I was wondering if the rules as you’ve investigated and tested thoroughly still apply with the latest browsers. The use case I’m referring to is as follows:

    @import url(“a.css”);

    within the a.css several @import rules are used.

    I know this should not be used in this way, but I’m very interested in your vision about this case.

  84. … the @import is used in a style element in the head

  85. Marc: The rules are still applicable. Please refer to Joshua Bixby’s article Browser innovation and the 14 rules for faster loading websites. Wrt @import: it’s bad for performance to use @import.

  86. @Murray
    I’ve actually experienced the opposite in regards to caching when using @import from inside a linked CSS file. Basically, the browser caches the files that are @imported and disregards future updates to them without the user force refreshing the page (Ctrl+F5). This is the issue that brought me to this post. I haven’t had much luck using a series of linked CSS file, the ordering and overriding of styles by later files doesn’t seem to work.

  87. Hi Steve,

    Please tell the impact on caching of @import & link.
    If i am going from page to another in the same website and both the pages using same css(which is already downloaded), then will it be downloaded for the second request as well?

    Does this depend on whether we use @import or link?

  88. Romit: The caching of a stylesheet is based on its response headers. Whether @import or link is used does not affect caching.

  89. I was looking for an answer as to if it is better to include two stylesheet links in the head or if to include one style sheet with an @import in that style sheet.

    really keen to know the best practices so if anyone has an idea of which would be better that would be great!

  90. when I use the instead of @import, my parent CSS sheet isn’t properly being imported and by styling breaks. Can you advise ont he best way to import my parent sheet into the child theme sheet?

    this is the parent i am trying to import: http://www.travelgrom.com/wp-content/themes/purity-child/style.css

    this is the child with the import rule: http://www.travelgrom.com/wp-content/themes/purity-child/style.css