Problem

  • Modules are not able to provide (default) styles for a particular theme.

Goal

  • Allow modules to provide styles for themes.

Details

  • Normally, modules should provide styles that work in Stark and hopefully in most other themes.
  • Themes in Drupal core are able to provide or override the styling for a specific module through known/usual ways, i.e. the theme ensures proper styling for everything.
  • However, since core and a couple of contributed themes slowly become more generic and re-usable, modules need a way to provide a theme-specific stylesheet to make their output look consistent with the rest of a particular theme, such as Garland, Seven, or Bartik.
  • To properly support theme-specific styling in the first place, module stylesheets should be separated into two files:

    vertical-tabs.base.css - structural/behavior styling
    vertical-tabs.theme.css - generic styling for Stark and other themes

    Any theme, including core themes, is therefore able to only override the design/look of the module's stylesheet, without having to deal with generic/structural/behavior styling. That alone heavily simplifies maintenance of CSS file overrides in core and contrib themes.

  • However, just splitting styles does not resolve the issue at hand, as modules are still not able to provide specific styles for certain themes, with focus on core's default themes.

Proposed solution

  1. Make drupal_get_css() (or similar) scan each added file for a .theme.css substring and automatically determine whether there is a theme-specific stylesheet for the current theme or base theme(s) in the directory of the stylesheet; i.e.:

    • When sites/all/modules/foo/vertical-tabs.theme.css is requested
    • And the current theme is Bartik
    • And Bartik would have the base themes Zen and Stark
    • Then check for the files:
      1. sites/all/themes/bartik/vertical-tabs.theme.css — the current theme's .theme.css always wins.
      2. sites/all/modules/foo/vertical-tabs.bartik.css — the module-provided default styles for Bartik.
      3. sites/all/modules/foo/vertical-tabs.zen.css — the module-provided default styles for the base theme Zen.
      4. sites/all/modules/foo/vertical-tabs.stark.css — the module-provided default styles for the base theme Stark.

Notes

  • jQuery UI more or less implements the identical pattern of $plugin.base.css and $plugin.theme.css to separate "logic" from design, and dynamically replaces .theme.css with an actual jQuery UI theme override.

Original summary

During a Bartik sprint, johnalbin & I were talking about how contrib modules *should* be writing their default markup as generic as possible (basically, make it look good for the Stark theme) but right now a contrib module that does this, but also wants to also include some styles to override another core theme (like Garland, or hopefully Bartik ;) ) they have no way to do that.

SOOOOO... we propose that the machine readable theme name for the current theme be included in the body classes on all core themes.

Thoughts?

Comments

johnalbin’s picture

Category: feature » bug

Yeah, I actually can't think of a better way to do that.

Right now core themes can't include styling for a contrib module because the contrib space moves too fast; the CSS rules that apply when the core theme is committed may not apply later.

So it becomes the responsibility of the contrib module providing reasonable styling for core themes.

Officially, we want the default CSS provided by a contrib module to give reasonable styling to the default templates and styles provided by core (as exposed by the Stark theme.)

But, there's no way for that contrib module to know whether or not the default theme on someone's site is Garland or Seven or Bartik or Corrolla, etc… That's a bug.

sun’s picture

Component: theme system » markup

Proper component. This sounds like Skinr to me. I'd love to hear Jacine's stance on this.

jacine’s picture

Hmm... I love the idea of separating the generic vs. design related CSS in modules, but is a body class the best we can do? I'd much rather see code separated into different files, i.e:

vertical-tabs.css (structural/behavioral stuff)
vertical-tabs-bartik.css (anything theme/design related)

I am growing tired of having to completely override module CSS files, and I think that just throwing a body class at the problem might just make it worse in terms of (a) giving many a body class they will not want, and (b) potentially including a bunch of CSS that isn't even applicable for a given theme.

bleen’s picture

I think I'm missing something ... the use case that JohnAlbin and I were talking about at DrupalCon was this:

Lets say I am a module developer and I make a new FOO module. I do my best to make all the markup and css as generic as possible but I notice that for the Garland theme (and only for the Garland theme) my FOO module desperately needs an override of some style in garland/style.css. I have no way to make that change without making it across all themes.

I'm not sure I see how splitting up structural css and design css will address this use case.

I might be misunderstanding, but I think that I am coming at this from the point of view of the module developer overriding core ... and you are coming at it from the site builder overriding modules & core.

Thoughts?

sun’s picture

I agree with Jacine that properly splitting generic and theme-specific styles into separate files would be a prerequisite. But rather:

vertical-tabs.css (structural/behavior stuff)
vertical-tabs-theme.css (makes it look good in Stark and hopefully most other themes)

Adding a body class won't help much. For one, you'd have to always load all styles for all supported core/contrib themes, regardless of whether they are enabled or used. Second, you'd have to add classes for the theme, but also the base theme.

In the end, a theme is responsible for properly styling page elements. Adding logic for that for modules slightly sounds like a step in the wrong direction.

bleen’s picture

Redacted ... dumb comment

jacine’s picture

vertical-tabs.css (structural/behavior stuff)
vertical-tabs-theme.css (makes it look good in Stark and hopefully most other themes)

This is good too. I was thinking that the file could contain the name of the theme and get auto-loaded when that theme was active, but this is better (easier for the module dev IMO).

bleen’s picture

How about both Jacine's & Sun's suggestions:

vertical-tabs.css (structural/behavior stuff)
vertical-tabs-theme.css (makes it look good in Stark and hopefully most other themes)
vertical-tabs-bartik.css (makes it look good in Bartik theme)

This way module developers can make a generic -theme.css but if they need to make any changes that are specific only to the bartik theme, then they have an easy way to do so.

Thoughts?

jacine’s picture

In theory I really like the idea. In practice, I worry that module developers will think they are being asked for too much, but maybe I'm wrong on that...? I also worry that it's too late to make such serious changes like auto-loading files by theme at this point.

The good thing about @sun's suggestion is that it wouldn't require any changes to core to implement now. Another good thing is that it would be really easy to wipe out all CSS files ending in -theme.css! :P

sun’s picture

Title: add machine-readible theme name as class to body tag » Modules are not able to provide styles for a core theme

Better title.

This issue only has a chance for D7, if someone is willing to spend quite a lot of time with reworking almost all .css files in Drupal core and core themes. If no one is willing to do that, we should stop dealing with it now and defer it to D8. If you are willing to do that, then please assign this issue to yourself.

Summary

Normally, modules should provide styles that work in Stark and hopefully in most other themes. Themes in Drupal core are able to provide or override the styling for a specific module through known/usual ways, i.e. the theme ensures proper styling for everything. However, since core and a couple of contributed themes slowly become more generic and re-usable, modules need a way to provide a theme-specific stylesheet to make their output look consistent with the rest of a particular theme, such as Garland, Seven, or Bartik.

To properly support theme-specific styling in the first place, module stylesheets should be separated into two files:

vertical-tabs.css - structural/behavior styling
vertical-tabs.theme.css - generic styling for Stark and other themes

Any theme, including core themes, is therefore able to only override the design/look of the module's stylesheet, without having to deal with generic/structural/behavior styling. That alone will heavily simplify maintenance of CSS file overrides in core and contrib themes.

However, properly splitting out the styles is a major job on its own and needs a dedicated force of people working on this issue.

Furthermore, just splitting styles will not resolve the issue at hand, as modules are still not able to provide specific styles for certain themes, with focus on core's default themes. To make this work, http://api.drupal.org/api/function/drupal_get_css/7 (or a better location) would have to scan each added file for a .theme.css substring and automatically determine whether there is a theme-specific stylesheet for the current theme or base theme(s) in the directory of the stylesheet.

i.e. when

sites/all/modules/foo/vertical-tabs.theme.css

is requested, and the current theme is Bartik, and a hypothetical Bartik has the base themes Zen and Stark, check for the files

sites/all/modules/foo/vertical-tabs.stark.css
sites/all/modules/foo/vertical-tabs.zen.css
sites/all/modules/foo/vertical-tabs.bartik.css

in the same directory, and conditionally load the theme-specific file instead -- but only if the theme itself does not provide a theme-specific CSS file override, in which case

sites/all/themes/bartik/vertical-tabs.theme.css

always has precedence.

That theme CSS file override functionality is handled by drupal_get_css() currently. Which is interesting, because the AJAX framework does not invoke drupal_get_css()... (separate issue)

Interestingly, jQuery UI more or less uses a similar pattern of $plugin.base.css and $plugin.theme.css to separate "logic" from design. We don't need a "base" suffix, but at least the .theme.css would be in line with a common pattern of jQuery UI.

jacine’s picture

Interestingly, jQuery UI more or less uses a similar pattern of $plugin.base.css and $plugin.theme.css to separate "logic" from design. We don't need a "base" suffix, but at least the .theme.css would be in line with a common pattern of jQuery UI.

Funny, jQuery UI was exactly what I was thinking of... I like the way they do this.

This issue only has a chance for D7, if someone is willing to spend quite a lot of time with reworking almost all .css files in Drupal core and core themes. If no one is willing to do that, we should stop dealing with it now and defer it to D8. If you are willing to do that, then please assign this issue to yourself.

As much as I would LOVE to take this on right now, I likely will not have the time to dedicate to make it happen over the next couple of months. I would definitely commit to helping with it as much as possible, but would want to know that it's something Dries/webchick would support. Even without the changes to drupal_add_css(), this would still be incredibly beneficial to all themers! So, if it's to late this time around, it could be one of our Drupal 8 goals!

jacine’s picture

Version: 7.x-dev » 8.x-dev

Not much activity here... Changing to 8.x.

mfer’s picture

subscribe

Nathan Smith’s picture

Subscribin' :)

tim.plunkett’s picture

Subscribing after Jacine's awesome blog entry.

seutje’s picture

This is an awesome idea, but do note that it makes reaching IE's 31 limit a real risk

I wouldn't consider this a stopped, unless a default core install already reaches that limit, because that would effectively mean that some1 who installs core for the first time and views it with IE is going to get a rather fugly mess of half-styles and such...

jacine’s picture

A fix for the IE limit went into D7, so as long as that holds, and it better - we're good!

bleen’s picture

Note: Another change that went in here #769226: Optimize JS/CSS aggregation for front-end performance and DX makes it possible that we would still hit the magic number of 31. Before this issue, it was very very very very unlikely that anyone would hit that magic number, and now it's just very very very unlikely... take a look at comment #131 for a good summary of whats going on. It still shouldn't be a problem, but its worth keeping in mind what is going on...

Basically, that issue says that there are some css files that shouldn't be part of the aggregated css file (by default) like those that are "admin-only" css files. In that issue we are currently working on getting stylesheets[] into module.info file.

sun’s picture

Title: Modules are not able to provide styles for a core theme » Split CSS files into structure/behavior and theme styles to allow modules to provide styles for themes

Please stay on topic. It's of no help to turn this issue into a meta issue. If there is any constructive suggestion to resolve #769226, then please don't hesitate to follow up over there.

This issue is about splitting CSS files into behavior and theme styles, so to allow modules to provide styles for themes.

mthart’s picture

subscribe

Jeff Burnz’s picture

Subscribe for future reference.

mxmilkiib’s picture

subscribe.

(hmm, for a checkbox that does nt subscribes..)

sun’s picture

In #885228-16: CSS Files are in major need of clean up!, we've started to clean up system CSS files and came to the conclusion that, hopefully, we can already extract "theme"-only styles into a system.theme.inc for D7 already.

Before creating a dedicated issue for this move, we should be 100% sure about the new filename and the file's contents. Let's discuss that here.

Please note that the issue/action will be limited to system.(theme.)inc only. Perhaps can be understood as test-drive for D7-8. This issue remains to change the global concept for D8.

jacine’s picture

Status: Active » Needs review

Of course I love the idea of test driving this in Drupal 7, and if it's too much to change right now we can do it in stages:

D7 Current File D7 Proposed File
admin.css system.admin.css
system.css system.theme.css
system-behavior.css system.css
system-menus.css no change
system-messages.css no change

Assuming that all goes well, we can finish the rest in D8, or we can decide to do something else...

D8 Current File D8 Proposed File
system-menus.css system.theme.css
system-messages.css system.theme.css

This gets would ultimately get us to 3 files in the end:

  1. system.css: structure/behavior styles
  2. system.admin.css: site-wide administrative styles
  3. system.theme.css: site-wide generic (design) defaults

But yeah, if this is going to have any chance of happening in D7, people need to speak up now. I've tried to outline what I think should happen, most of it here, but that's about as much as I can do. I hope that everyone is on board, but obviously people need to speak up either way ASAP.

sun’s picture

I'm concerned about #885228: CSS Files are in major need of clean up! then. Ideally, we'd try to do as much as possible in one shot, so as to remove the the burden from other reviewers and core maintainers.

Upfront: system.admin.inc is a no-brainer, doesn't need any discussion, but just a patch to rename the file (in a separate issue). Can land whenever it's ready. Other patches in the queue can be quickly corrected by adjusting the filename in the .patch file.

However, as mentioned over there (but maybe not too clearly), I think there's a gap in the proposed files:

system.css and system-behavior.css are 2 files, but contain 3 different things: (Directly appending my thoughts/proposal to keep it simple)

1) Structural fundamental default baseline stuff like .element-hidden and .clearfix. These should be in a separate file, as you most likely won't ever want to override them. For instance, system.base.css.

2) Basic styles for various Drupalesque elements, such as links, forms, pagers, etc. This is totally theme specific and very likely overridden by a theme, thus system.theme.inc.

3) Styles that are related to various different JavaScript behaviors, of which none actually belong to system.js or System module. Because of the unique purpose, keeping them in the file system-behavior.css (instead of system.css) makes sense to me. More on this below.

Thus, we'd have system.base.css, system.theme.css, and system-behavior.css.

As I've already mentioned over in #892486-1: Put navigation-related styles from system module in system-navigation.css, one other real world theming problem I'm regularly facing is that you want your theme to

- override the styles for collapsible fieldsets only, but you have to override the entire styling for all behaviors.

- override the styles for any other unique individual behavior, but you have to override the entire styling for all behaviors.

IMO, when talking about preprocessed/aggregated files, we should split them even further into more atomic topics. I want a

misc/collapse.css for collapsing fieldsets, a
misc/textarea.css for resizable textareas, a
misc/autocomplete.css
misc/tabledrag.css
misc/tableselect.css
misc/progress.css
misc/tableheader.css

...so I can override collapse.css and only collapse.css in my theme, while it's still aggregated into the default aggregate.

EvanDonovan’s picture

Subscribing. I would like to see the amount of CSS in Drupal core be made as minimal as possible. This approach (making it more granular) sounds like it might have benefits, but I worry that it would be confusing to new themers if the number of new files is increased too dramatically, and would also dramatically increase the number of CSS files being served to the client when CSS aggregation is not on.

The change from #885228: CSS Files are in major need of clean up! looks nice though, since it moved things around without introducing new files.

UPDATE: I read Jacine's blog post on fixing core CSS. I think I understand more what you're driving at here. This might be the best alternative - better than removing all the core CSS, as some people have suggested.

Anonymous’s picture

Status: Needs review » Active

Setting to active. Needs review is reserved for patches AFAIK.

sime’s picture

@design_dolphin, not technically correct, it's just common practice. Solutions that need review are not always patches.

I won't change it back as the review status was set a while ago.

aspilicious’s picture

Subscribing and adding a note:

With these new files being added, due to the splitting of the css, files are scattered around in the module directory.
I asked in irc why we don't put all the css files in a css directory. The answer was that this is mainly a *theme* thing. I disagree as I see plenty of modules with a css folder alrdy and it makes the structure more readable.

EvanDonovan’s picture

I think a css directory for modules would actually be a good precedent to set in core.

bleen’s picture

module/css ++

jide’s picture

Totally agree with sun (I was about to make the exact same proposition). It will help reduce overall CSS size, make them modular and easier to override, component by component. The rule could be : one theme function, one CSS file, attached in the theme function. When you think of it, attached JS files most of the time follow this logic already.

BarisW’s picture

By the way, why are we storing system.base.css in the system module folder and tabledrag.js in misc?
Wouldn't it make more sense to save all Drupal system CSS files in just one directory?

Can we come up with a - kind of - definite list of CSS files? I'm willing to work on it, but I could use some more input.

What about...

core/modules/system/css/system.admin.css
core/modules/system/css/system.admin-rtl.css
core/modules/system/css/system.base.css
core/modules/system/css/system.maintenance.css
core/modules/system/css/system.theme.css
core/modules/system/css/system.theme-rtl.css
core/modules/system/css/misc/collapse.css
core/modules/system/css/misc/textarea.css
core/modules/system/css/misc/autocomplete.css
core/modules/system/css/misc/tabledrag.css
core/modules/system/css/misc/tableselect.css
core/modules/system/css/misc/progress.css
core/modules/system/css/misc/tableheader.css

More?

sun’s picture

Title: Split CSS files into structure/behavior and theme styles to allow modules to provide styles for themes » Allow modules to provide styles for themes (finally leverage structure/behavior split of CSS files)
Component: markup » CSS
Category: bug » task

Wow, quite the discussion here. :) Apparently, the split into .base.css and .theme.css ultimately happened already :)

The essential, remaining part is the proposal in #10, which still makes sense to me.

Views has just been added to core, which basically contained a massive workaround for this issue, in order to provide sane CSS styling for the core themes when it wasn't in core yet — now that it has been moved into core, those CSS styles have been moved into the respective core themes. (Which, on its own, circles back into the problem space of #575298: Provide non-PHP way to reliably override CSS, since all of those styles are unconditionally loaded within those themes now.)

I'll move #10 into the issue summary in a moment.

sun’s picture

Issue summary: View changes

Updated issue summary.

sun’s picture

Issue summary: View changes

Updated issue summary.

lewisnyman’s picture

Status: Active » Closed (won't fix)

As far as I understand the goals of this issue, is to allow modules to provide nice theming for their output that is inline with a specific theme, because it's not possible for Bartik to override the styling of contrib modules, which means new output can't match the look and feel of Bartik/Seven/etc.

Our new CSS standards define an OOCSS approach, which allows us to define design component in reusable classes. In the Seven theme we're taking the approach of abstracting a lot of the look and feel into utility classes, see https://groups.drupal.org/node/454113. This means modules can match the look and feel of Seven without writing any CSS.

Bartik is moving more towards this abstraction approach as well, if we eventually implement #1804488: [meta] Introduce a Theme Component Library it would mean a shared library of reuseable components across themes that modules can hook into and avoid writing their own CSS.

This feels like a much cleaner solution then asking modules to write custom CSS for specific themes, so I'm going to close this issue. Thanks!