This issue is mirroring a similar one re: drupal_add_js(). The general gist is that the $css array that gets built in the drupal_add_css() function is not modifiable by another function or the theme. This means that if a module or theme wants to *remove* or otherwise *alter* the list of CSS files being output to the page, there is not a good way to do this.
I see two different options for fixing this situation:
1) Use a global variable for $css instead of a static variable. This would obviously make it super-easy for any function to modify the array.
2) Use a drupal_alter() call inside of drupal_get_css() and allow modules to implement hook_css_alter(). This seems like a lot more overhead to me, but it does avoid adding more variables in the global scope. It also ensures correct execution order without having to weight the modules doing the altering. This method would not work for themes though -- since themes can't implement hooks.
3) Both
Use case: Many CSS developers are frustrated by the amount of CSS that Drupal adds. They have a hard time "undoing" what Drupal has already done in order to get their site to look the way that they would like. The main complaint that I hear is about the menu styling in system.css. Allowing modification of the $css array would allow themes to either remove these core css files or copy them into the theme directory and then replace them in the $css array. This was the main complaint expressed by the Full Code Press team in this interview.
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | d6-add-css-ref.patch.txt | 826 bytes | jjeff |
Comments
Comment #1
Crell commentedOption 1, Globals: If globals are the answer, you're asking the wrong question. :-) We should be using fewer globals, not more.
Option 2, hook_css_alter: I am not opposed in principle, but I'm not sure I see the need. Modules should not be playing with each other's CSS. The theme already can in the preprocessing function nee _phptemplate_variables(). Themes can also now override a parent theme's CSS via the info file.
I guess I don't see the use case here that isn't already covered.
Comment #2
jjeff commentedI've figured this out and the solution is VERY simple. In order to get the returned $css value to pass by reference (and therefore allow other functions to alter), we simply add a
&before the function name.This patch does just that. Simple.
Solves all above problems without global variable or new hook.
Comment #3
jjeff commentedHow to alter the CSS array after the patch has been applied:
Fun stuff!!!
Comment #4
Crell commentedYes, nice and simple. But again, what the heck is a module doing screwing around with another module's CSS? That's the theme's job, for which there is already a mechanism (albeit not perfect).
Comment #5
dvessel commentedfyi, this queue right here tried dealing with the issue already. Was postponed for 7.x
http://drupal.org/node/163785
Comment #6
jjeff commentedThere is NOT currently a mechanism for the theme to do this. If the CSS aggregator is enabled, then the theme can only ADD CSS files, NOT remove them.
Also, there are cases where a theme or theme engine (perhaps a Flash-based theme, or a mobile-oriented theme engine) might want to redefine core or module CSS files. I realize that the styles can be redefined, but it's just not very efficient to a) have to figure out all of the selectors and specificity in order to overwrite what core is doing, or b) add extra download code just to remove CSS.
Please listen to this podcast starting around 13:30 to hear the problem that the Full Code Press team had in being unable to remove the CSS that was being added by core.
There are also probably a few cases where it would be nice for a module to be able to remove existing CSS files. If this patch were applied it might be possible to create a module called (something like) menu_styles.module which could offer choices for bullet styles on the menu blocks, replacing the core menu styles. Again, I realize that this could be handled by adding more CSS files, but this is the best example I could come up with off the cuff. ;-)
Comment #7
jjeff commentedAnother use case: I would like for the Zengine theme engine to be able to allow theme developers to copy any core/module CSS file into the theme directory in order to redefine it. This is currently impossible because once a CSS file has been added with drupal_add_css() it is impossible to remove/redefine it.
Comment #8
dvessel commentedjjef, I totally agree it should be simplified and made easier for themers to do what they please with core or any style sheets for that matter. I listened to the podcast and found it *very* interesting seeing it from a new perspective. Thank you for doing that. If I could make a request here, I'd say bring in more people that are new to Drupal to interview so everyone else too close to Drupal can gain more insight. Work with Drupal long enough and you start to forget how complicated it can get if you don't know the system well.
Yes, it's possible to remove core styles sheets right now but it's not straight forward and we need to fix that. I hope I can contribute to that in 7.x. I think the easiest approach is to have directives (is that the right word?) inside .info files that tell Drupal what to do like using the file system to discover overrides or simply simply switching them off completely.
Here's a handbook page on using the file system for 5.x. It can be easily adapted for 6. Your last use case for doing it through the theme engine is possible with the same technique. In fact, I plan on creating an engine myself to do the same.
http://drupal.org/node/155400
As far as modules overriding style sheets, I am totally against that. As Crell mentioned, modules have no business messing with other styles.
Comment #9
jjeff commenteddvessel: Ahhh... okay... I didn't realize that drupal_get_css() took $css as an argument. I guess this approach works and can solve my theming problems.
I still think that we shouldn't be limiting what modules can or cannot be doing to the CSS, but as long as I can handle this at the theme level, I'll loosen up on the urgency of this issue.
I still think think this type of alteration should be available for the $javascript array in drupal_add_js() though (see other issue). And it makes sense to keep both of these functions "in sync", so if the & makes it in over there, it might warrant revisiting it over here.
Comment #10
hass commented@jjeff: thats wrong. I have build a theme that "unset" a css file and later add it back... thats working in D5. Look here:
Comment #11
catchThis still applies (not surprising, it being one character). But going to bump for D7 since it clearly needs more discussion.
Comment #12
lilou commentedPatch #2 still applied.
Comment #13
catchDoesn't seem to be much support for this, so marking to won't fix.