Dear folks,
When we make a website using Drupal, almost every module have a CSS file and Drupal load it in every page. Just for an example, I have a small install of D7 in my machine with the core, views and ctools, just it. To load the homepage, Drupal load 13 different CSS files, including one for views, one for ctools, 4 from core (system module), 2 for fields, etc. For me, this is a huge amount of files with a big problem: each file is a request for the server (that's make the website slow).
If I check the compress option inside the performance, the number of the files drop to 5 but, IMHO, still big. Th be worse, I would like to manage the CSS files to put some files in some pages and other set of files (code is better) in other pages.
What's the best approach to work with this situation? How can I drop this number of files? The unset function is the best solution or not?
I'm glad to hear the opinion of the masters here.
Best,
Paulino

Comments
The advagg module is supposed
The advagg module is supposed to be able to aggregate, minify and compress CSS/JS, but the current D7 does absolutely nothing. The framework is there, it's just not functional.
Both drupal_add_js() and drupal_add_css() have options to not load the files on every page, and modules should use the render array's '#attached' property anyways, as to load the CSS/JS only when necessary.
What I do for some sites is use hook_js_alter (for example, in your template.php) to offload some scripts to the footer, i.e. making them load asynchronously. Makes your website feel a lot faster. You could also try out the labjs module.
The current status of aggregation is pretty poor, and hopefully the D7 version of advagg will be functional pretty soon.
+1 on that. I've been waiting
+1 on that. I've been waiting for this.
Premium Drupal Commercial themes
The addition of
The addition of hook_css_alter with D7 improved the situation greatly and makes adv_agg less necessary.
You're definitely supposed to
You're definitely supposed to run in "Aggregate and compress CSS files" mode. Allowing each module to have its own css file is really the only feasible way to have add on modules, but it can result in lots of files. The performance option is there to solve the problem.
In D6 the aggregator put all the files in one giant file. D7 groups css into a few different files for a couple reasons. One, if a module is only present on one page, then D6 creates an entire new aggregated css file for that page, and makes the client download 99% of the same css that it already has in its cache. D7 separates out "every_page" files from css that only appears on some pages. Also, sometimes css needs to appear in order, so it's not overwritten, e.g. resets need to appear first. So D7 not only allows you to give a weight to each file but also groups the files into three categories, CSS_SYSTEM, CSS_DEFAULT, and CSS_THEME. So between the three groups and the every_page switch, you can have 6 different aggregated files.
This isn't as much of a problem as you think for two reasons. First, they only get downloaded on the first page, and then your server should be signalling the client to cache the files for all future pages. And two, modern browsers now download around six files in parallel, as opposed to the old days where it was as low as two. So even on that first page, depending on the user's browser, you might be getting all those css files at once.
OK, but that's not to say there isn't room for improvement and customization. For example, I use the Panels module a lot and I use panels_everywhere. So the Panels dev says "people don't necessarily use Panels on every page, so I'll mark it as every_page=false". However, I use Panels on every page, so creating a new request for those silly 12 lines of panel-only css is silly. So I solve the problem with this:
<?php
function MYTHEME_css_alter(&$css) {
// These are used often, just merge them with the other module css
if (module_exists('panels')) {
$css[drupal_get_path('module', 'panels') . '/css/panels.css']['every_page'] = TRUE;
}
if (module_exists('ctools')) {
$css[drupal_get_path('module', 'ctools') . '/css/ctools.css']['every_page'] = TRUE;
}
}
?>
The same is true of ctools. This merges the Panels and Ctools css in with the other module every_page css and saves me a request for the tiny module files.
So...
1. there's good reasons for the way that it is doing what it is doing;
2. the performance impact is actually pretty small with caching;
3. if you want to optimize from the general defaults to more specific settings for your site, you can.
Nice answer
Dear Brian,
Thanks a lot for your answer. It's give me some insights but, in the other hand, now I have more questions.
I understand how Drupal manage the CSS files and, of course, the reasons to do that (and your explanation was great at this point) but, today, Drupal remain using a lot of CSS files to do... nothing and I think that we need a new approach or a new way to manage this situation better.
For example, if we install 20 modules, normally we have 20 CSS in the front-end. Of course, we can aggregate them in 5 or 6 files but are 5 or 6 files that the user need to download from the server.
You say "the performance impact is actually pretty small with caching" and it's true but not for the first access. What I'm saying is: when a user comes to the website in the first time, he need to download everything for build the page. This task is fast if we have a great cache system where we can reduce the size and time to download all files.
But, If the page have 6 CSS files, the user's browser need to download them (in parallel or not) and make 6 connections to the server. That's the point for me. If the page have 6 CSS with 10kb each or 6 CSS with 100 bytes each, still are 6 files and 6 connections.
My question is not about the size of the files but how much files the user need to download form the server in your first visit. This question comes from a situation when I prefer to create a fast experience to the users in the first visit, giving a fast landing page to them. For this, in different CMS's, I make just one CSS file for the landing page, putting everything that I need for this web page inside of this file and, after that, use the regular system with different CSS files, cache systems, etc.
I don't know if someone use the same approach of me. If not or if I'm wrong, I would like to know and share the ideas.
Thanks!
Paulino Michelazzo
http://www.michelazzo.com.br
Yes, I'm Brazilian and we don't speak Spanish here (but I can speak too).
I agree, frontend performance
I agree, frontend performance is greatly reduced by all those server connections waiting for each other, even in parallel. I really like the LabJS approach, but for some scripts (e.g., horizontal/vertical tabs), the change in styling is so large, it looks rather quirky when loaded after the site has been rendered for the most part.
Your approach makes sense, but it's not really the ideal situation, as it requires manual adjustments. Using hook_js_alter() and hook_css_alter(), you should be able to alter it to your taste, even on a per-theme basis.
Also, one thing I found is to prevent media queries in the elements, i.e. using options with drupal_add_css(). Rather put them inside the CSS-files, so that they can be aggregated into a single file. Not sure if this affects browser performance, though.
That's the idea Martijn, use
That's the idea Martijn, use some module to aggregate the CSS files with a little help of my hands.
Best,
Paulino Michelazzo
http://www.michelazzo.com.br
Yes, I'm Brazilian and we don't speak Spanish here (but I can speak too).
In short, if you combine
In short, if you combine everything into one CSS file and one JS file, then because CSS/JS varies slightly from page-to-page, you are forcing visitors to re-download all CSS/JS every time they visit a new page. Drupal's default tries to strike a balance between performance for a single-page, vs. performance if a user visits multiple pages that may contain different CSS/JS.
--
Dave Hansen-Lange
Director of Technical Strategy, Advomatic.com
Pronouns: he/him/his
I share your thoughts about
I share your thoughts about optimizing css. With asynchronous loading of javascript, css is the one blocking element that prevents the user from seeing something on the screen.
If we use an asynchronous javascript loader, then the items blocking initial rendering are one connection for each css file, and say one connection for lab.js. Nearly all modern browsers make 6-8 connections at once. http://www.browserscope.org/?category=network
I personally do not believe two or three or even four css files will delay initial rendering in most cases. The parallel downloading may even speed it up in some cases.
There could be several
There could be several different kind of bottlenecks in this case. One is CPU/rendering wise as you described above and another is network-wise. If you have ever tried to browse modern sites with GPRS, you noticed the DNS-requests (because of CDN, because of cheap bloggers combines files from google.com, dafonts.com, github, etc. in the same time) and different HTTP-requests are pain and easy to lost the connection. On limited or noisy network, combined files offer better performance and solves the blinking re-rendering after every new downloaded file.
Aries
Sandbox
In the last 2 weeks I've been working on the D7 version of advagg. Once I get a couple more minor things working I'll be merging in the D7 sandbox.
http://drupal.org/node/1927578
I had to rework the code from the ground up due to all the D7 changes. While in here I decided to change the naming scheme of the files.
From http://drupalcode.org/sandbox/mikeytown2/1917800.git/blob/9a7bae90e071b0...
By doing this, it allows for an aggregate on one site to be used in another as what is used when generating it will be the same. It make this issue possible http://drupal.org/node/1082928
Great
This is a great news. Thanks for the update. advagg is a great module to work with this issues.
Paulino Michelazzo
http://www.michelazzo.com.br
Yes, I'm Brazilian and we don't speak Spanish here (but I can speak too).
Mikeytown2, thanks for the
Mikeytown2, thanks for the update! If you need someone to test the module when possible, I'd be pleased to. Many of my sites could certainly benefit from it.