Any way to add CSS for a single page/node?

by epersonae   Last Updated January 13, 2018 18:07 PM

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.)

Tags : 7 theming panels


Answers 14


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

In the template.php you will want something like:

function 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.

Decipher
Decipher
March 02, 2011 23:53 PM

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

CSS:

The CSS module adds, for users with enough permissions and enabled nodes, a CSS field on the node creation page.

Users might insert CSS rules in the CSS node field and those rules will be parsed on the node viewing.

This way CSS experienced users might create complex CSS based design for nodes contents.

Important: note that the CSS editing permissions should be given only to trusted users (administrators). Malicious users which have this permission might broke your site design and also introduce security issues (XSS).

Paul Jones
Paul Jones
March 03, 2011 00:03 AM

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.

Camsoft
Camsoft
March 03, 2011 00:12 AM

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.

Dave Reid
Dave Reid
March 03, 2011 00:13 AM

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

Context:

Context allows you to manage contextual conditions and reactions for different portions of your site. You can think of each context as representing a "section" of your site. For each context, you can choose the conditions that trigger this context to be active and choose different aspects of Drupal that should react to this active context.

Think of conditions as a set of rules that are checked during page load to see what context is active. Any reactions that are associated with active contexts are then fired.

Context Add Assets:

Context add assets allows you to do this. It has an easy to use UI to allow you to do this all without writing any code. Because it uses ctools all of this is also exportable.

budda
budda
March 03, 2011 00:43 AM

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

rakke
rakke
May 30, 2011 15:59 PM

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");
  }
}
kiamlaluno
kiamlaluno
June 06, 2011 00:35 AM

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.

Warpstone
Warpstone
September 12, 2012 14:39 PM

/* 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
}
tal
tal
September 12, 2012 18:30 PM

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.

Alexander Hripak
Alexander Hripak
November 02, 2012 20:28 PM

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.

Druvision
Druvision
December 25, 2012 21:45 PM

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

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

augusto
augusto
November 22, 2013 11:41 AM

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.

mixerowsky
mixerowsky
August 13, 2014 14:48 PM

You can print the page node in the body-tag

<body page-node-26419 ...>

Then you can restrict

body.page-node-26419 {
    background: red
}

This is useful for minor quick changes

Markus Zerres
Markus Zerres
January 13, 2018 17:32 PM

Related Questions



How do I preprocess a particular Panels Pane?

Updated March 20, 2017 05:07 AM


How to allow users change theme for specific pages

Updated August 05, 2017 10:07 AM

Panelizer setup

Updated September 27, 2017 10:07 AM