This was discussed a little bit in http://drupal.org/node/137211 and it was agreed it needed to be put off for its own patch. This issue is here to discuss the merits of the idea.

What I'm thinking is that we do have this:

stylesheet = the basic stylesheet. AKA style.css. This stylesheet is only loaded if this is the actual theme being used. Right now this is singular, but we should expand this to be an array.

required stylesheets = Any stylesheets that will be loaded, whether or not this is the actual theme being used. This should be an array.

So in practice, a theme like zen (which has style.css, content.css, icons.css, etc) would list most of its stylesheets in 'required stylesheets' and style.css is mellow. Children of zen wouldn't get the base style.css but would get the rest of it.

The question is...do we want to add in something so that a child theme can do anything about the required stylesheets? I'm thinking we probably do not, but I want to hear opinions.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dvessel’s picture

Need time to absorb all the theme changes.

subscribing for now. :)

Crell’s picture

I'm not sure I'd differentiate between "required" and "not required" stylesheets. That effectively cripples a subtheme's ability to override certain parts of a parent. OK, they could just edit the parent theme's .info file, but that rubs me the wrong way just like the words "hack core" do. :-)

I was thinking just a simple list to list stylesheets. Example:

garland.info:
stylesheet[] = style.css
stylesheet[] = icons.css

minelli.info:
stylesheet[] = icons.css

So garland.info provides two stylesheets. minielli then replaces one by name, so its icons.css will be used instead of garland's icons.css, but both will use garland's style.css.

The question then is how to completely remove a parent sheet. I see two alternatives with this method. Either have a double-named list (stylesheet[icons.css] = icons.css) so a child theme can specify empty string for a given sheet to disable it or allow the child to provide an empty file to override with. The CSS caching mechanism would take care of the otherwise unnecessary extra file.

I'm not a huge fan of either, honestly, but it's 2 am so it's the best I can think of right now. :-) I'll try to remember to ask our themers at work on Monday.

add1sun’s picture

Hm, i'll have to think on this more in general but of the two ideas proposed by Crell I'd say option 1 is better but not pretty. Creating an empty css file is well, a PITA and messy (I'm a bit of a neat freak so unnecessary files bug the crap out of me). IF we let children do anything other than actual css overrides, it should be a setting. But I'm not familiar enough with all the new changes and info files to give an intelligent alternative right now.

Ands’s picture

Title: Allow multiple stylesheets in the .info files » new
Version: 6.x-dev » 4.6.9
Component: theme system » menu system
Category: task » bug
FileSize
69 bytes
add1sun’s picture

Title: new » Allow multiple stylesheets in the .info files
Version: 4.6.9 » 6.x-dev
Component: menu system » theme system
Category: bug » task

fixing this dammit

nickd-1’s picture

Title: Allow multiple stylesheets in the .info files » Allow multiple stylesheets in the .info files

(I'm one of Crell's said themers.)

I agree with Crell that forcing "required" stylesheets isn't ideal - that's like using the !important syntax in CSS, and when you have conflicts on that front, it could get ugly. I'd like to avoid this if at all possible, as it hinders flexibility.

What you have right now (to my understanding) is the child theme's stylesheets get called second so their styles override previous ones in priority. So if you have an element styled on the parent that's done differently on the child, child wins. I'd like to see a similar mapping in v6.

_Un_setting parent stylesheets is a separate issue. In my limited experience, all one can do with unsetting stylesheets is to do so in template.php in the parent theme. I'd like to have similar functionality in the child theme, so I won't need to override a bunch of styles in order to redo a page substantially. That could be very powerful in situations where subpages have drastically different styles, so that I wouldn't have to rely on body classes and could instead use themes. The CSS would be cleaner, if broken into many different files.

Crell’s picture

After a bit more brainstorming with nickd, what about something like this:

garland.info
stylesheets = style.css icons.css foo.css

minelli.info
stylesheets = style.css
remove_stylesheets = icons.css

Minelli then gets its own style.css, Garland's foo.css, and no icons.css at all. Child themes can easily cherry pick, parent themes require no modification, and the syntax is kept nice and simple.

moshe weitzman’s picture

i'm not so sure that stylesheet overrides belongs in .info. a theme receives an array of stylesheets already. surely it could perform whatever changes it pleases. we could make that manipulation easier, if it is awkward today. just wondering if we are abusing .info. we had this debate about regions so feel free to tell me to STFU and look there.

this might come down to a matter of taste.

Crell’s picture

There's 2 reasons I'd like to see theme .info files able to exclude style sheets.

1) Themers can futz with their stylesheet list without getting into template.php. If we didn't have full theme inheritance then it wouldn't be as much of an issue, but suppose you wanted to inherit from a big theme to get its .tpl.php files but didn't want any of its CSS? You'd have to have an "override" CSS file for every CSS file in the parent, or else lots of re-defines to undo what the parent does. Either one gets ugly fast.

2) Sure that could be done in template.php, but that means the stylesheet array is compiled twice. That's wasteful.

morphir’s picture

I don't know if info files are the best solution.
What about .config ?
or .theme.conf ?
or just .conf ?
It makes more sense IMHO..

Also, I would love to mix stylesheets in that .info file like this:

<nodetype> = <css files....>
story = layout-2.css, color-6.css, typography-2.css
news = layout-3.css, color-6.css, typography-2.css
forum= layout-8.css, color-7.css, typography-1.css, icons.css

This approach relay on css-layouts entirely. And by mixing them together, you can cook together your own page designs and colors(as well as typography) with ease.

morphir’s picture

After reviewing http://drupal.org/node/132018 I whitdraw my suggestion on .conf naming etc.

Crell’s picture

Assigned: Unassigned » Crell
Status: Active » Needs review
FileSize
8.15 KB

So I decide to give this a shot. The attached patch changes the .info file syntax for stylesheets from "stylesheet" to "stylesheets[]". Themes can declare as many stylesheets as they want. If they specify nothing, style.css is still used. Themes also inherit all stylesheets from their base theme, unless they have a stylesheet of the same name in which case it is used instead of the one from the base theme.

Doesn't do any "remove stylesheet" magic yet. I figure save that for a later patch. It also occurs to me that now that we have the JS compressor in core as well, doing the same thing for theme-provided scripts should be easy and useful.

I also have modified Garland to split its CSS file into two, mostly for demonstration purposes. That part can be left out of the real patch if desired. I just needed a test case. :-)

Crell’s picture

Title: Allow multiple stylesheets in the .info files » Allow multiple stylesheets and scripts in the .info files
FileSize
9.94 KB

Rerolling for HEAD. While I was at it, I threw in multi-JS support as well. It's essentially the same code but says "scripts" instead of "stylesheets". Committers: You can probably leave out the changes to Garland. They're just for demonstration purposes.

Gábor Hojtsy’s picture

Get dww review this :) He often has strongs arguments about what to put into .info files and what not to put there.

dww’s picture

sorry, i don't know enough about themes and the problems facing themers to have a strong opinion. in principle, this seems like a reasonable thing to put in the theme .info files, but i really can't be considered the resident authority on such matters. people who actually know about this should have much more say in the outcome of this issue than i do. the things i know about are release management, packaging, stuff like that. stylesheets and js are for the theme-aware to argue about. ;)

dvessel’s picture

Personally, I'm not too concerned about how this comes together inside .info files. As long as there's a way around it (which there is), it's all good.

But just to throw the idea out here, how about using the file system as an option. Everyone knows how to drop files into folders.

For example, in the parent themes' directory:

stylesheets
--all
----style.css
----layout.css
----colors.css
--print
----print.css
--screen
----etc.css

The sub-theme:
stylesheets
--all
----colors.css.disabled (disables parent colors.css)
----layout.css (overrides layout.css in parent)

This way it can handle media types and it's intuitive. I'm guessing it can be simple with the glob() function to read all the files in one fell swoop.

Getting back on the immediate topic, Crells' latest approach is nice and simple. Tested without problems.

theborg’s picture

Any of the two approaches are good, and I'd love to see one of them in core. We need to have more control over css files to be more effective designing themes.

Also I think we should have the hability to override/disable modules css, either by info files or with an option on the themes configuration forms (or with a css module configuration form).

Crell’s picture

I'm wary of imposing magic directory naming on themes. My themers always seem to have as strong an opinion on the name of their stylesheet directory as coders do about brace positioning. :-) Valid point regarding media types, although that's not a feature we offer now anyway except via template.php.

Module overrides would be good, too, but I'm not sure of the best way to do that. Right now, this code just queues up more drupal_add_css() calls when the theme is initialized. Removing from the list would require pulling the array and regenerating, which is generally done in template.php. IIRC the CSS array also has paths in it, so we'd have to iterate and do substring or drupal_get_path calls to figure out which to remove. That could get expensive.

Also, #13 does allow theme CSS overriding already. If you have a file with the same name as a parent theme's CSS, it gets used instead even if empty. The CSS aggregator then takes care of it being an empty file. It's not the cleanest setup, which is why I didn't document it, but I don't think it's much less clean than foo.css.disabled.

dvessel’s picture

@theborg, overriding module styles from core would be nice but it's not hard to do from the theme. I've been meaning to put up a handbook page on it and you just reminded me. :) http://drupal.org/node/155400

For now, I think Crell's patch works well.

Crell’s picture

OK, I just had a (marginally) brilliant idea. The new ini file format accepts nested keyed arrays. So we don't need the directory structure at all to break up media types. Instead we do something like this:

styles[all][] = styles.css
styles[all][] = icons.css
styles[print][] = print.css
styles[remove] = icons.css

Where "remove" is understood as being not a media type but the "skip this from a parent theme" list. All other values are treated as a media type and passed to drupal_add_css() accordingly. Alternatively we could still use styles_remove[] =. I don't know off hand which would be easier to code. (Even without the remove flag it's still a worthwhile improvement.)

Thoughts? I think #13 is a decent fallback if anyone wants to RTBC or commit it, but unless someone objects I'll try to roll the above design soon.

Crell’s picture

FileSize
11.2 KB

And here we go again, with full media type support! Once again, bastardizes Garland and Minelli for demonstration purposes only.

This patch does not contain an explicit override. On further review I'm not sure it needs it. The theme system already does a file_exists() check in list_themes(), so if a file doesn't exist it won't be added anyway. That means you don't even have to provide a dummy file; just re-declare a media/file in a sub theme and poof, it's gone. With proper documentation (which I will be writing) I don't think that's any less obscure than an override array that we'd also have to name and explain and parse. This way the code and info syntax is kept nice and simple and we get the override ability for free.

I ran this syntax past two of my themers this afternoon, and both liked it.

Speak fast, for the ice age approacheth. :-)

theborg’s picture

It works nice for me and I like the syntax.

Just eliminate this line from page.tpl in garland theme because it loads print css two times:

style type="text/css" media="print">@import "<?php print base_path() . path_to_theme() ?>/print.css";</style>

About module css, I think we have to study it carefully (maybe on the next version), I dont want to impact on performance but we should work on helping themers without hacking functions on template.php. For now dvessel solution is very good! :)

dvessel’s picture

Tested, and it works well. I'm not so sure about redeclaring in sub-themes to override. Seems counter intuitive.

What about having a separate array labeled as "disabledstyles" or something similar then arraymerge so you get the same effect?

dvessel’s picture

err, scrap that idea since it wouldn't really be disabled if the style is overlooked and left in the sub-theme. Would be confusing.

Crell’s picture

dvessel: I think it's more intuitive to redeclare in the subtheme that you're going to use a given stylesheet than to have to declare that it shouldn't use the one from the parent and then also redeclare that you're going to provide one. It's one statement instead of 2. That it is then also useful for "removing" stylesheets from the parent rather than just replacing them with your own is a convenient bonus. :-)

I'll try to get time later to remove the print stylesheet from garland's page template, after which I hope this will be RTBC. :-)

Crell’s picture

FileSize
12.01 KB

Here we go.

dvessel’s picture

FileSize
8.34 KB

I meant redeclaring in order disable sub-theme styles seems counter intuitive. Most people I'd think would figure adding to the styles array means adding to the page. Having a duel purpose keeps the code clean but still confusing at first. It would have to be documented and I guess I can handle that part. I'm back to reworking the theming handbook.

The latest patch still had style.css split apart and demo script files for Garland. Here it is removed. I also changed some of the other core themes to use this convention that supply more than one style.

pwolanin’s picture

reading through the patch code in detail it looks good

pwolanin’s picture

Status: Needs review » Reviewed & tested by the community

Testing this it seems to work well, and would be a really good use for the new .info files for themes.

dvessel’s picture

Nice Crell, hope it gets in soon. :)

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Needs review

Can someone explain in simple terms what was not possible without this patch, and what is the value with using this? Some theoretical examples would also be nice. I looked through all the technical discussion here, but this is not clear to me.

pwolanin’s picture

Gabor - Garland provides a prime example:

it comes with two style sheets, but in order to use them, the second one has to be hard-coded into the page.tpl.php.

What this patch enables is simply adding as many stylesheets as you want via the .info file, and (especially combined with http://drupal.org/node/125428) the system or modules can deal with them in an appropriate way via the CSS aggregator, etc.

Right now, only 1 style sheet for any theme will be loaded and aggregated by the system.

As second useful example is that it allows a theme to have a file with a name other than style.css as the sole stylesheet.

The same arguments hold for scripts as well.

Gábor Hojtsy’s picture

OK, now reviewed the patch with this in mind. It makes a lot more sense :)

- "// Now do the same for scripts." is not right, it implies I already read the comments above. It should be a simple description on what happens there.
- dvessel said he changed "some of the other core themes"... did he change all core theme which are possibly affected?

Crell’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
8.55 KB

Attached patch just duplicates the commentary for scripts and stylesheets, to address Gabor's comment. No other changes.

The patch tweaks both Garland's and Chameleon's info files. It doesn't change the others, because it doesn't need to. If nothing is specified, it defaults to the equivalent of stylesheets[all][] = styles.css, just like the old version. There's no need to explicitly declare that in the other core themes.

Crell’s picture

FileSize
8.55 KB

Now how DID that stray letter k get in there...

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Fixed
FileSize
8.61 KB

Maybe it was not telling enough, but when writing #33, I did review the patch line-by-line (*), so it was clear that default style.css and script.js files are added to the array. What was not clear is whether other core themes might require it, and the existing comments above did not clean that up either. Thanks for cleaning that up and for the updated patch.

The actual patch I committed is attached. Done these modifications to Crell's code:

- default scripts and default stylesheets was not accurate when calling the drupal_add_*() functions, we add all sheets and scripts
- 'scripts' needed this plural form when doing proper path manipulation

Please update the theme update guide!

(*) The fact that I only found these two things to say was a sign of how good the code looked for me.

Crell’s picture

w00t. Thanks, Gabor.

There's two related CSS patches that are also pending, if you're interested. They both make CSS handling easier for the theming set:
http://drupal.org/node/145218
http://drupal.org/node/125428

jbjaaz’s picture

What about stylesheets fed via IE conditional comments? Often time, IE needs special hacks in order for css to render properly. IE conditional comments is a clean way to keep messy hacks out of stylesheets.

Something similar to the following would follow the syntax Crell introduces in #20
styles[all][ie][lte 6] = ie.css --

styles[all][ie][7] = ie.css --

styles[all][ie][] = ie.css --

I realize this might be more trouble than it's worth. Just a thought.

jbjaaz’s picture

Something else that I've thought about. Basically, when you define a stylesheet, you're locked in to
<style type="text/css" media="all">@import "style.css";</style>

What if I wanted to use the link element instead? It'd be nice if the code that produces <style type="text/css" media="all">@import "style.css";</style>, was themeable so I could ultimately decide how my stylesheets were linked into the document.

Crell’s picture

Re different ways of adding CSS to the page: http://drupal.org/node/145218 :-)

Re IE: Honestly I have no particular interest in designing our info format around a 7 year old buggy browser that is in rapid decline. (IE 7 is rapidly replacing IE 6, and Firefox is still rising.) You can do conditional comments now in the page template yourself, which is fine as far as I'm concerned.

Anonymous’s picture

Status: Fixed » Closed (fixed)