After searching for several hours for a clean solution on how to remove a particular core/module stylesheet from the stylesheet queue, I've only found some dirty hacks like this one.
The given solution (replacing print $styles; by $css = drupal_add_css(); unset($css['all']['module']['foo']); print drupal_get_css($css); in page.tpl.php) is definitely not a clean one since it needs code in a place where such code simply shouldn't be.
From a themer's perspective I wondered why there is a drupal_add_css() but not a drupal_remove_css() function. From this POV and taking the time for finding a dirty solution into account, this can certainly be categorized as bug.
To come straight to the point: The attached patch for common.inc introduces the function drupal_remove_css($path = NULL) that
- extends
drupal_add_css()with an argument to remove a given path - can be called from a theme (f.e. in template.php) or any module that wants to override another one.
Example: To remove Drupal's default stylesheet from the queue, simply put this line into template.php:
drupal_remove_css('modules/system/defaults.css');
This patch is simple, straightforward and will help many users to get their sites up & running in less time.
Overriding core and contrib module styles is one of the most annoying actions in building a new Drupal theme.
| Comment | File | Size | Author |
|---|---|---|---|
| #31 | remove_css.patch | 1.82 KB | eaton |
| #9 | alter_css_2.patch | 2.17 KB | pwolanin |
| #6 | alter_css_1.patch | 522 bytes | pwolanin |
| drupal_remove_css.patch | 1.99 KB | sun |
Comments
Comment #1
pwolanin commentedSomehow I thought one could do this already in 5.x, but don't see it now.
Anyhow, this doesn't seem like quote the right approach, since you need to be able to do this after all modules/themes have added their CSS, right?
Comment #2
sunI don't think there is another way to disable specific stylesheets as you do not know if and when a particular one is added to the queue by a core or contrib module. Since this is a theming issue and one Drupal installation could be used to deliver more than one site or theme, a theme designer can only remove stylesheets at theming level, i.e. in template.php. AFAIK, all stylesheets are already added to the queue at theming level.
Please also bear in mind that this is only a bug fix that saves time (and money). It's obvious that a feature request for a more complete CSS handling solution for 6.x+ would likely introduce a more modular concept, so f.e. the current drupal_add_css() would become drupal_manage_css() along with the helper functions drupal_add_css() and drupal_remove_css(). But that is not part of this issue.
Comment #3
smk-ka commentedMaybe the approach that drupal_add_js() is using could be of use for you?
Comment #4
drummThis is an API change so I would call it a feature. It needs to go in the development version and will not hit the stable 5.x versions.
Comment #5
pwolanin commentedThe patch seems to only really handle the case of media == 'all'.
I'm not sure what the possible concerns are of having such code in template.php, but that's also not a good way to handle this- not all themes have such a file that's included.
One possible approach (requires a module) to this would be to add a call to drupal_alter to drupal_get_css():
If you want themes to be able to do this - that's harder. The principle of theme functions is to return HTML, not manipulate data. however this seems like a case where something like theme('alter_css', $css) would be justified?
This could be called in function template_preprocess_page()?
Comment #6
pwolanin commentedAs shown above. A simple one line patch to let modules alter the css queue before it's rendered.
Comment #7
merlinofchaos commented+1, but it seems like you'd also want to allow the theme to alter it. In fact, it's much more valuable to let the theme alter it, I would think.
Comment #8
solipsist commented+1 from me on this one too... I agree that this should be possible at theme level, it's where it's needed the most I would think. It's important from a performance POV too since instead of overriding CSS, themers could disable modules' CSS files and replace them entirely with their own.
Comment #9
pwolanin commentedAfter discussion with merlinofchaos in IRC, I went ahead an implemented the part to allow the theme to alter too. This diverges a bit from the normal use of theme functions (it has to return an array) but that seems to be the only reasonable way to let themes do this. I tested both parts of the patch. With the latter part you can make your site look ugly by putting in Garland's template.php:
Comment #10
dmitrig01 commentedyes
Comment #11
alpritt commented+1
Just quickly adding that this functionality will be extremely useful from a themer's perspective.
The negative, of course, is that this is not particularly intuitive for a non-coder. But that is a wider and more difficult problem with theming that shouldn't hold up this commit.
Comment #12
alpritt commentedhmm, not sure how that happened. Changing back the status.
Comment #13
sunLooks great!
Thanks, pwolanin, for taking this up.
Comment #14
douggreen commentedI checked out the latest code from cvs head, applied the patch with no problems. I ran two tests.
+1
Comment #15
pwolanin commentedimproving the title
Comment #16
Crell commentedThis works fine for me, and complements this patch wonderfully. (That one adds CSS, this one removes it.) My only problem is the name. theme_* functions are expected to behave in one way. *_alter functions are expected to behave in another. theme_css_alter behaves like... which? My first guess was like an alter hook, but it's actually a theme function. That's confusing.
I'd prefer a name other than "alter_css" for the theme function to avoid confusion with the alter workflow. Otherwise this is ready to go.
Comment #17
Crell commentedLike I said, it compliments this patch. *sigh*
Comment #18
dvessel commented+1
I found some workarounds that works well within themes but this would simplify that.
Comment #19
m3avrck commentedAs the write of the original patch that added drupal_add_css() to core I don't like this approach.
The cleanest approach to do this is to create your phptemplate_variables() and add:
This patch doesn't really make that process any simpler and adds more overhead IMO.
Comment #20
pwolanin commentedI think this approach is less overhead - since you alter the css array before the files are loaded and aggregated. With your appreach, won't every file have to be loaded again?
Comment #21
m3avrck commentedIt's just manipulating an array with that code and then it rebuilds the CSS cache.
I agree -- it's not the best, but I don't think this method here makes it any simpler... or maybe I'm reading it wrong (perhaps too tired ;-))
Comment #22
alpritt commentedTwo issues have been raised (comments #16 and #19) which need to be resolved before we can say this is ready, so I'm pushing this back to 'needs work'.
Comment #23
sun@#16: Please correct me if I'm wrong.
theme_css_alter()is both a theme_* and an *_alter function, which is actually doing the trick. Whilst theme_css_alter() is invoked by drupal_alter(), garland_css_alter() is invoked by the Theme system. Each theme can implement its own theme_css_alter() function.@#19: The great benefit of this patch from a themer's perspective is that there is a official "best practice" to achieve the targeted result - no more custom hacks and a solid ground for further improvements in the future. Without an implementation like this (as of now) we force themers to either use Drupal's default stylesheets or to implement custom hacks found on d.o. I agree, it's far from perfect. But with a simple explanation and a cross-reference to drupal_add_css() in the API, themers won't be stuck anymore.
Setting this back to RTBC.
Comment #24
alpritt commentedI'm totally in favour of this feature, but I'm no longer convinced this short term solution is a good response to the problem.
Re: solid ground (#23): I'm not sure this is true. The implementation of this looks like a clever hack to me, and I'm not sure it's really something we can build on. Unless we are gaining something substantial from this in the short term, I'm against it. This is part of the API that themers will have to learn, and I don't want them to have to unlearn something if we can avoid it. This just feels like we are rushing in the hope of getting it into Drupal 6.
I personally think the sister patch (http://drupal.org/node/141725) has a good strategy for this kind of thing. Using the .info file is not only easy, it is arguably easier than coding it with plain old HTML. This is a very positive move. The more theme related stuff we can take out of PHP functions the better.
To avoid a ping-pong match I'll leave the status alone.
Comment #25
sun@alpritt: The referenced patch deals with adding stylesheets to a theme only. I'm not able to think of a way to remove core and module stylesheets through a definition in a theme's .info file.
Hm. Maybe this way?
The downside of this approach would be that a themer might not know
[all][module]and is not able to determine the array keys without executing PHP again.Comment #26
alpritt commentedLooks like this has hit the code freeze.
I suggest we first make sure there is a clear workaround documented in the handbook and then postpone this for d7.
Hopefully by then I'll have be more comfortable with the core code, so will actually be more useful ;)
Comment #27
pwolanin commentedA clarification - I thought that naming the theme function using the same pattern as the _alter function would simply things - but perhaps not. The theme function could be named anything (e.g.
theme('ihateothercss', $css)).Comment #28
webchickPast code freeze.
Comment #29
sun*sigh* just wanted to tell that I'm stuck again creating a new theme. While hacking my way using Ted's workaround in #19 I'm seriously asking from a themer's perspective, how this can be classified as a feature request.
If you'd ask me, this issue is the reason why many Drupal sites look quite similar - since we expect that themers know how to fix this bug.
Another particular use case of drupal_remove_css() was to be able to do
in template.php - in short: 1) remove user.css from preprocessed CSS queue, but 2) add it to non-preprocessed queue if needed.
Comment #30
pwolanin commented@sun - well if you feel strongly enough that it's a bug, change the version back and make your case.
Comment #31
eaton commentedHere's a shot at it -- it's definitely kludgey, but it could be a real boost for CSS-only .info file driven themes that just want to, say, turn off all of Drupal's default css files and control stuff like ULs and such themselves.
Comment #32
pwolanin commentedI assume Eaton is still hoping for 6.x.
Anyhow - I don't think this code is good, since themes cannot predict the path where contrib modules may be installed.
Perhaps a simpler patch could provide a mechanism for removing only core CSS or core required module CSS? Or replacing them rather than removing them?
Comment #33
eaton commentedWell, that's one of the reasons it's doing a string comparison -- if you put in modules/system/system.css, it will find that anywhere there's a modules folder. Your point stands, though. I'm not particularly HAPPY with it, but it's cleaner than any other method I was able to come up with.
It is a relatively small change. If it (or any similar improvements) go in, it should go in under the principle that 'anything that prevents users from making a reasonably simple CSS-only theme, without writing PHP code, is a bug in Drupal 6.'
Comment #34
eaton commentedOn pwolanin's suggestion, I'll avoid hijacking THIS issue thread and point directlly to the more 'focused' issue: http://drupal.org/node/163785. Thanks.
Comment #35
sunFrom a themer's point of view, I'd say that overriding core/module stylesheets is sufficient for creating any custom theme. If 163785 goes in, themers are able to place an empty/modified stylesheet into their theme folder that has the same name like a core/module stylesheet. If CSS preprocessing is enabled, even empty stylesheet files (replacements) won't hurt anyone.
Thus, marking as duplicate of http://drupal.org/node/163785