tags:

views:

535

answers:

7

Which is a better option: to store CSS on a separate file or on the same page?

Let's forget the fact that changing the CSS on a file makes it to apply all HTML pages directly. I am using dynamic languages to generate the whole output - so that does not matter.

A few things I can think of: 1) CSS on a separate file generates less bandwidth load. 2) CSS on a separate file needs another HTTP request.

On the other hand, if I compress the data transmission with Zlib, the CSS on the same page should not matter in terms of bandwidth, correct? So, I get one HTTP request less?

+27  A: 

The main benefit of an external CSS file is that:

  • It can be used on multiple pages; and
  • It can be cached so it doesn't need to be loaded on every page.

So, if there is potential for reuse of the dynamically generated CSS between pages or on multiple views of the same page then an external file could add value.

There are several common patterns for dynamically generated CSS.

1. Generating a subset for a page

I've seen this occasionally. A developer decides to limit the amount of CSS per page by only sending what's necessary. I don't imagine this is the case for you but I'm mentioning it for completeness. This is a misguided effort at optimization. It's cheaper to send the whole lot and just cache it effectively.

2. User-selected theme

If the user selects a particular look for your site, that's what I'm talking about. This implies they might select a whole package of CSS and there might be a limited set to choose from. Usually this will be done by having one or more base CSS files and then oen or more theme CSS files. The best solution here is to send the right combination of external CSS files by dynamically generating the page header with the right <link> elements and then caching those files effectively.

3. User-rolled theme

This goes beyond (2) to where the user can select, say, colours, fonts and sizes to the point where you can't package those choices into a single theme bundle but you have to generate a set of CSS for that user. In this case you will probably still have some common CSS. Send that as an external CSS files (again, caching them effectively).

The dynamic content may be best on the page or you may still be able to make use of external files because there is no reason a <link> can't point to a script instead of a static file. For example:

<link rel="stylesheet" href="/css/custom.php?user=bob" type="text/css">

where the query string is generated dynamically by your header from who is logged in. That script will look up the user preferences and generate a dynamic CSS file. This can be cached effectively whereas putting it directly in the HTML file can't be (unless the whole HTML file can be cached effectively).

4. Rules-based CSS generation

I've written a reporting system before that took a lot of rules specified by either the user or a report writer and a custom report and generated a complete HTML page (based on the tables and/or charts they requested in the custom report definition) and styled them according to the rules. This truly was dynamic CSS. Thing is, there is potential for caching here too. The HTML page generates a dynamic link like this:

<link rel="stylesheet" href="/css/report.annual-sales.0001.css" type="text/css">

where 'annual-sales' is the report ID and 0001 is like a version. When the rules change you create a new version and each version for each report can be cached effectively.

Conclusion

So I can't say definitively whether external CSS files are appropriate or not to you but having seen and developed for each of the scenarios above I have a hard time believing that you can't get some form of caching out of your CSS at which point it should be external.

I've written about the issue of effective CSS in Supercharging CSS in PHP but the principles and techniques apply in any language, not just PHP.

You may also want to refer to the related question Multiple javascript/css files: best practices?

cletus
Kai Sellgran says: "Let's forget the fact that changing the CSS on a file makes it to apply all HTML pages directly. I am using dynamic languages to generate the whole output - so that does not matter."
Kriem
@Kriem: Exactly.I do not care about the flexibility of having a one place to edit CSS - I have the CSS on my database and it's outputted to all pages automatically. I am using Zlib output compression, so, the CSS consumed bandwidth is extremely low. In addition, I save one HTTP request.
rFactor
@Kai: The fact that it is cached if external means that you are saving one HTTP request once until the cache is expired. Plus, you are saving bandwidth since you are not resending useless non-changing information on every request.
Andrew Moore
@Kai: The fact that you're using Zlib is irrelevant unless you believe that Zlib can compress a file to less than 0 bytes. Since the page is dynamic, the CSS will have to be resent with every page load if it's inline. If it's an external file, since the CSS itself won't change very often, the browser can cache it and won't have to reload that data.
Chuck
Thanks for the comments.The CSS code seems to be around 1 kB in size after compressed. I am willing to take that bandwidth consumption. Besides, you don't need to do additional HTTP requests for CSS files. Even if you cache the CSS file, you still need to do it initially and at some point again.Basically I have come to this point:External CSS:+1 Initial HTTP request+1 Potential HTTP request later (no cache enabled, cache is full, cache is cleared or it is invalidated)Internal CSS:+1 kB more bandwidthI decided to took the ladder option.
rFactor
+1 for caching.
Soviut
+1  A: 

Browsers can cache the CSS files (unless it changes a lot). The bandwidth should not change, because the information is sent, no matter where you put it.

So unless the css quite static, putting it in the page costs less time to get.

Ikke
My experience says that CSS-files (and all other modules) are loaded separately, so many small files results in many small connections. So the bandwidth itself might not change indeed, but in matter of performance I'd suggest to limit the number of stylesheet files if the information I just provided is correct.
Ivarska
If the files don't change, this hit would only happen the first time someone visits the page. After that, the browser can use the cached version. Altough, I think the browser still makes a request to check if hit hasn't changed.
Ikke
+1  A: 

I always use mix of both.

  • site-wide styles are in separate file (minified & gzipped),
  • any page-specific styles are put in <style> (I've set up my page templates to make it easy to insert bits of CSS in <head> easily at any time).
porneL
A: 

Keep it separate. HTML for centent, CSS for style, JavaScript for logic.

Raf
+9  A: 

There is a method that both Google and Yahoo apply which benefit's from inline CSS. For the very first time visitors for the sake of fast loading, they embed CSS (and even JavaScript) in the HTML, and then in the background download the separate CSS and JS files for the next time.

Steve Souders (Yahoo!) writes the following:

[...] the best solution generally is to deploy the JavaScript and CSS as external files. The only exception I’ve seen where inlining is preferable is with home pages, such as Yahoo!'s front page (http://www.yahoo.com) and My Yahoo! (http://my.yahoo.com). Home pages that have few (perhaps only one) page view per session may find that inlining JavaScript and CSS results in faster end-user response times.

Török Gábor
Yes, yes, yes. I'd upvote this more if I could.
Anirvan
+1  A: 

If you're generating HTML dynamically (say, from templates), embedding CSS allows you the opportunity to also generate the CSS dynamically using the same context (data, program state) as you have when you're producing the HTML, rather than having to set that same context up again on a subsequent request to generate the CSS.

For example, consider a page that uses one of several hundred images for a background, depending on some state that's expensive to compute. You could

  1. List all of the several hundred images in rules in a seperate, static CSS file, then generate a corresponding class name in your dynamic HTML, or
  2. Generate the HTML with a single class name, then on a subsequent request generate CSS with a rule for that name that uses the desired image, or
  3. Do (2), but generate the CSS embedded in the HTML in a single request

(1) avoids redoing the expensive state computation, but takes a larger hit on traffic (more packets to move a much larger CSS file). (2) Does the state calculation twice, but serves up a smaller CSS file. Only (3) does the state calculation once and serves the result in a single HTTP request.

Dave W. Smith
A: 

Yes and no. Use a .css file for most rules; your site should have a consistent look anyway. For rare, special case, or dynamically generated rules you can use inline 'style=""'. Anything that sticks should move into the .css, if only to make transcluding, mash-ups, etc. easier.

Matt Willtrout