Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I'm cleaning up my big crazy style sheets (possibly pertinent to a future question) and I'm wondering the best way to add custom CSS to a specific node or page.

In particular, my work site's home page is a Panel Page and it has a bunch of different styling. Right now the CSS is just included with the main theme style sheet.

Is there a way to say, "if this is node Foo, then add foo.css"? Is CSS Injector what I'm looking for?

I might be interested in generalizing this to other nodes/sections/etc, but at the moment I just want to handle this one item.

What I ended up doing.

I'm using a Zen subtheme, and discovered in actually reading through template.php that there's some commented out code for including conditional style sheets. Code below did exactly what I needed:

if (drupal_is_front_page()) {
  drupal_add_css(path_to_theme() . "/foo.css", 'theme','all'); 
}

(Line 80 in a stock Zen template.php file, FWIW.)

share|improve this question
    
Related: drupal.stackexchange.com/questions/736/… –  chrisjlee Aug 25 '11 at 15:12
    
create page--front.tpl.php and page.tpl.php –  Drupalist Aug 13 at 15:17

13 Answers 13

up vote 43 down vote accepted

This is the sort of thing that I'd do by code, but that's because that's just the way I role.

In the template.php you will want something like:

MYTHEME_preprocess_node($vars) {
  if (drupal_get_path_alias("node/{$vars['#node']->nid}") == 'foo') {
    drupal_add_css(drupal_get_path('theme', 'MYTHEME') . "/css/foo.css");
  }
}

Replace foo with values related to your own code.

share|improve this answer
    
so for the home page, would you use if(drupal_is_front_page()) { instead of if(drupal_get_path_alias [etc]? –  epersonae Mar 2 '11 at 23:59
    
Yes, the conditions are entirely up to you. You could simply do a $vars['#node']->nid == $nid check if you wanted. –  Decipher Mar 3 '11 at 0:06
3  
Decipher, can't find any fault with your code. But hope you don't mind me pointing out that unless you are talking about Drupal permission configuration, the way you role should actually be the way you roll. ;-) –  medden Jun 28 '12 at 7:23
2  
FYI, I'm using Drupal 7 and found that I needed to use $vars['elements']['#node']->nid instead in the alias lookup. There's no #node root in vars in the latest Drupal 7 from the looks of it. –  Wes Johnson Feb 14 at 21:50
    
shouldn't it have function ahead of MYTHEME__preprocess_node($vars) I see all the code in there just being in terms of functions? –  pal4life Jun 5 at 22:57

You could have a look at the Code per Node module. It is also featured in this blog post.

share|improve this answer

Create a Context for your page/section and then use the Context Assets module to load CSS and/or javascript for that given context.

share|improve this answer
    
I use Context Add Assets in literally every website I make - if your into Context's (which drive every section of my builds) Add Assets is perfect! –  electblake Mar 16 '11 at 21:03

If it's a small amount of CSS, maybe considering making your CSS selectors based on the node and including the css in your theme's CSS? Drupal 7 provides the body.page-node-NODEID selector, and Zen for Drupal 6 provides similar body CSS classes.

share|improve this answer
    
that's basically what I was doing...and it's almost 200 lines, so it seemed like a good idea to move it elsewhere. (yes, it should probably be shorter. that may be a separate step.) –  epersonae Mar 3 '11 at 0:27
    
On the other hand, your response inspired me to read the template.php in my (Zen child) template, which got me to the final answer. –  epersonae Mar 3 '11 at 0:28

You could create a custom module and use hook_preprocess_node() to load stylesheets selectively based on the node id.

Here's an example:

function MYMODULE_preprocess_node($vars) {
  $nid = 3;
  if (arg(0) == 'node' && is_numeric(arg(1)) && arg(1) == $nid) {
    drupal_add_css(drupal_get_path('theme', 'MYTHEME') . "/foo.css");
  }
}

Replace MYMODULE with the name of your module and replace MYTHEME with the name of the theme that contains the css file.

share|improve this answer
    
hook_init() runs on every page load, and often multiple times (AHAH), why not use hook_preprocess_node() (either in the theme or in a module) which only runs when a node is rendered? –  Decipher Mar 3 '11 at 0:15
    
Good point, did not know that init was loaded multiple times. –  Camsoft Mar 3 '11 at 0:19
    
Decipher, I've corrected my example to use the preprocess function. Still learning! –  Camsoft Mar 3 '11 at 0:27
    
Then the next question would be why use arg(1) for the nid when the node variables are passed through $vars :) Which would then lead to the next question of how is this different to my answer :p –  Decipher Mar 3 '11 at 0:30
    
I guess I should have read the hook_preprocess_node() documentation. You're absolutely right. epersonae, I suggest you accept Decipher's answer. –  Camsoft Mar 3 '11 at 0:32

For an admin based way of doing it I'd look at the CSS module. Adds a field where you can add CSS to the node/add and node/edit pages.

share|improve this answer

If the criteria for which adding a CSS style depends from some properties of a node, then I would implement MYTHEME_preprocess_node(&$variables); one of the values passed to the function is $variables['node'] (to notice it's not $variables['#node']).

MYTHEME_preprocess_node(&$variables) {
  if ($variables['node']->nid == 3) {
    drupal_add_css(drupal_get_path('theme', 'MYTHEME') . "/foo.css");
  }
}

If the criteria don't depend from any node properties, then I would implement MYTHEME_preprocess_page(&$variables); $variables['node'] contains a node object, if the page being shown is a node page. In Drupal 6, the process function also gets $variables['is_front'], but in Drupal 7 the same variable is not passed; if you need to know if the page is the front page, you need to use drupal_is_front_page().

MYTHEME_preprocess_page(&$variables) {
  if ($variables['is_front']) {
    drupal_add_css(drupal_get_path('theme', 'MYTHEME') . "/foo.css");
  }
}
share|improve this answer

Since you're already using Panels, it might be easier to to just add your CSS as a Panel Style for each region of your homepage panel. You can define custom markup there and reuse it across your site.

You can also just go to the General section of the page manager variant rule for your homepage. There is a section here for adding CSS IDs and rules for only the current panel.

Note: this is all in D7, so it might be that this approach is better supported by Panels than it was in prior versions.

share|improve this answer

/* An example using bartik theme to add css based on content type */

function bartik_preprocess_node(&$variables) {
if(!empty($variables['node'])) {
    if($variables['node']->type == 'my_custom_content_type')
    {
      drupal_add_css(drupal_get_path('theme', 'any_theme_name') . "/css/foo.css");   
    }
  }
  // Some other code here
}
share|improve this answer

I would've skipped touching template.php altogether and just add another item in your theme's .info file

Say your stylesheet is in css/foo.css.

This is how your theme_name.info file would look:

name = Theme Name
...
stylesheets[all][] = css/foo.css

Then you benefit from having it cached with the main stylesheets, and since I'm assuming this is for your homepage it would make sense.

share|improve this answer
    
And of course you would need to qualify your selectors based on the node's attributes, i.e. nid, node type, etc –  Alexander Hripak Nov 2 '12 at 20:30
    
The problem with this approach is it will affect all the pages on the site with the css added here –  pal4life Jun 6 at 15:03

CodePerNode is great, but CSS Injector is simpler to install (no libraries needed). The module allows the content manager to dynamically add CSS to specific pages, without touching PHP code or INFO files at all. 15777 installs can't be wrong - this is a social proof this module works. The CSS is also cached with the regular caching system.

share|improve this answer

Aside the Drupal approach, when you only need a short piece of css inside your HTML5 body, you have the css scoped Attribute. See http://stackoverflow.com/a/4607092/195812

This solution will save you from editing code and installing more modules

share|improve this answer

Try to add this in your 'template.php' file:

function mytheme_preprocess_page (&$variables)
{
  if (drupal_is_front_page()) {
    drupal_add_css(drupal_get_path('theme','mytheme'). '/css/front.css');
  } 
}

Replace 'mytheme' with name of your theme directory and '/css/front.css' with path where is your CSS file.

To unset 'front.css' file from other pages try to add to 'template.php':

function hook_css_alter(&$css) {
  if (!drupal_is_front_page()) {
    unset($css[drupal_get_path('theme', 'mytheme') . '/css/front.css']);
  }
}

Again, replace 'mytheme' with name of your theme directory.

If you need to unset 'styles.css' from front page just combine these two codes.

Lets assume that you need 'front.css' without 'styles.css' on front page, and 'style.css' without 'front.css' on all other pages. Code will look something like this:

function mytheme_preprocess_page (&$variables)
{
  if (drupal_is_front_page()) {
    drupal_add_css(drupal_get_path('theme','mytheme'). '/css/front.css');
  } 
  else {
    drupal_add_css(drupal_get_path('theme','mytheme'). '/css/styles.css');
  }
}

function hook_css_alter(&$css) {
  if (drupal_is_front_page()) {
    unset($css[drupal_get_path('theme', 'mytheme') . '/css/styles.css']);
  }
  else {
    unset($css[drupal_get_path('theme', 'mytheme') . '/css/front.css']);
  } 
}

Also, replace 'mytheme'.

I hope this will be helpful.

share|improve this answer
    
The last piece of code is what I needed. And it works, i.e., after I removed stylesheets[all][] = css/front.css from my theme.info - I guess I assumed wrongly that we need to have that along with stylesheets[all][] = css/styles.css. I was also worried that because I'm overriding page.tpl.php with page--front.tpl.php it might not work but everything seems to be holding up nicely. This is truly helpful. Thanks! –  Sd1 Aug 13 at 17:29
    
You're welcome... –  mixerowsky Aug 13 at 23:06
    
Just to make sure everybody gets this solution; make sure to remove styles.css (the default) and front.css from your theme.info file. Flush all caches and it should be good to go. –  Sd1 Aug 14 at 17:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.