Customizing the CSS class of the body based on node type

Often, a theme developer may want to customize the areas of the page beyond the node content area based on the node type displayed. The page Customizing the full page layout and sections based on node type describes how to customize the overall layout. However, a great deal can be achieved using CSS - without the need for separate full page layouts.

If you only have node-type specific theme changes that can be accomplished with CSS, you can accomplish your goals by attaching a node-type-specific class to the HTML body tag. You've probably seen an example of this in action if you've used the Garland theme. The page.tpl.php file in the Garland theme directory calls a function in the template.php called 'phptemplate_body_class'. The function adds a class to the body based on if the left or right sidebars are displayed.

Step One:

If you haven't already, create a copy of a core Drupal theme such as Garland, rename it, and place it in your /sites/all/themes folder. (Unless you have a multi-site installation, in which case you would place it in the site-specific themes folder.) If you do not already have a template.php file in your theme, create it.

Step Two:

Define a new variable - $body_class - in the '_phptemplate_variables' function within the template.php file. This is an immensely useful function since it allows you to set variables that can be called in your page.tpl.php file.

<?php
function _phptemplate_variables($hook, $vars = array()) {
  switch (
$hook) {
    case
'page':
     
$vars['body_class'] = '';

     
// Set body class for formatting based on content type
      // if the node exists, i.e., if a node is the focus of the page.
     
$vars['body_class'] = isset($vars['node']) ? 'type_' . $vars['node']->type .' ' : '';

     
//Allows specific theming for taxonomy listings
     
if (arg(0) == 'taxonomy') {
         
$vars['body_class'] = 'taxonomy_list';
      }

     
/*
       * The following lines replace the phptemplate_body_class found in Garland
       * These are only necessary if you are still using the sidebar classes in the Garland theme
       */
     
$layout = '';
     
//Is there a left sidebar?
     
if ($vars['sidebar_left'] != '') {
         
$layout = 'sidebar-left';
      }
     
//Is there a right sidebar?
     
if ($vars['sidebar_right'] != '') {
          
$layout = ($layout == 'sidebar-left') ? 'sidebars' : 'sidebar-right';
      }
     
//Put layout into body_class
     
if ($layout != ''){
        
$vars['body_class'] .= ' ' . $layout;
      }
     
//End Garland-specific classes

      //Add additional class if this is the front page (for home page specific theming)
     
if (drupal_is_front_page()) {
        
$vars['body_class'] .= ' home';
      }

      break;
  }
  return
$vars;
}
?>

As an addendum, check out the variables created in the phptemplate_page function. This function generates many of the variables used in page.tpl.php. There is a $layout variable that stores whether the layout contains right, left or both columns. However, this variable may not work if you have created custom theme regions, so the code above demonstrates how to calculate it in the template.php file.

Step Three:

If your theme was based on Garland, you may delete the phptemplate_body_class function at this point since the classes have been incorporated into the _phptemplate_variables function above.

Step Four:

Finally, you need to modify the page.tpl.php file to call the $body_class variable.

<body class="<?php print $body_class; ?>">

Now, you can add node-specific CSS styles just by using syntax like the following (This example is for a CCK node type of 'person'.):

body.type_person #attachments {
background: #fff;
}

Much simpler than creating a new page.tpl.php file for each node type, and this is extensible if you add more node types.

 
 

Drupal is a registered trademark of Dries Buytaert.