Last updated August 27, 2009. Created on September 24, 2005.
Edited by ronald_istos, JohnAlbin, add1sun, sepeck. Log in to edit this page.

This code will create a body class and id for every page on your site.

In your theme’s page template (page.tpl.php), replace your existing body tag <body> with the following code:

<body<?php print phptemplate_body_attributes($is_front, $layout); ?>>

And add the following code to your theme’s template.php file:

/**
* Sets the body tag class and id attributes.
*
* From the Theme Developer's Guide, http://drupal.org/node/32077
*
* @param $is_front
*   boolean Whether or not the current page is the front page.
* @param $layout
*   string Which sidebars are being displayed.
* @return
*   string The rendered id and class attributes.
*/
function phptemplate_body_attributes($is_front = false, $layout = 'none') {

  if ($is_front) {
    $body_id = $body_class = 'homepage';
  }
  else {
    // Remove base path and any query string.
    global $base_path;
    list(,$path) = explode($base_path, $_SERVER['REQUEST_URI'], 2);
    list($path,) = explode('?', $path, 2);
    $path = rtrim($path, '/');
    // Construct the id name from the path, replacing slashes with dashes.
    $body_id = str_replace('/', '-', $path);
    // Construct the class name from the first part of the path only.
    list($body_class,) = explode('/', $path, 2);
  }
  $body_id = 'page-'. $body_id;
  $body_class = 'section-'. $body_class;

  // Use the same sidebar classes as Garland.
  $sidebar_class = ($layout == 'both') ? 'sidebars' : "sidebar-$layout";

  return " id="$body_id" class="$body_class $sidebar_class"";
}

Note: To use this properly you really need to have clean urls turned on.

Example of use:
Using this snippet, when going to news/archive/2007, you will see the following body attributes:

<body id="page-news-archive-2007" class="section-news sidebar-left">

So now all you have to do is create another rule that defines an alternative style for the entire news section:

.content { background-image: url("background.png"); }
.section-news .content { background-image: url("news.png"); }

If you enable the path alias module, and take the time to create a heirarchical path for each of your pages, you can create easily create site sections and apply a completely different layout (background image, colors, widths, etc) to each section.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

jorgemaestre@drupal.org’s picture

This is a function similar to drupal_set_title() that can be used by a developer to set de body class:

function common_set_body_class($body_class = NULL) {
  static $stored_body_class;

  if (isset($body_class)) {
    $stored_body_class = ' class="'.$body_class.'"';
  }
  return $stored_body_class;
}

Then pass your body class to your theme templates in template.php:

//$body_class for HTML body
$vars['body_class'] = vivu_common_set_body_class();

Change your body code to look something like this:

<body <?php print $body_class; ?>>

Anywhere in your code you can call the function to set the body class, for example when drawing your home page:

vivu_common_set_body_class('home');
lcampanis’s picture

If you are NOT using clean URLs use this function instead:

<?php
function phptemplate_body_attributes($is_front = false, $layout = 'none') {

  if (

$is_front) {
   
$body_id = $body_class = 'front';
  }
  else {
   
// Remove base path and any query string.
   
global $base_path;
    list(,
$path) = explode("?q=", $_SERVER['REQUEST_URI'],2);       
   
$path = rtrim($path, '/');
   
// Construct the id name from the path, replacing slashes with dashes.
   
$body_id = str_replace('/', '-', $path);
   
// Construct the class name from the first part of the path only.
   
list($body_class,) = explode('/', $path, 2);
  }
 
$body_id = 'page-'. $body_id;
 
$body_class = 'section-'. $body_class;

 

// Use the same sidebar classes as Garland.
 
$sidebar_class = ($layout == 'both') ? 'sidebars' : "sidebar-$layout";

  return

" id="$body_id" class="$body_class $sidebar_class"";
}
?>

This part has changed from the original function:

<?php
list(,$path) = explode($base_path, $_SERVER['REQUEST_URI'], 2);
list(
$path,) = explode('?', $path, 2);
?>

to

<?php
list(,$path) = explode("?q=", $_SERVER['REQUEST_URI'],2);
?>

Lorenzo.

nocean’s picture

To expand this to add a class for the status of the user (whether logged in or not), you can modify the function all in page.tpl.php and the function in template.php as so:

<body <?php print phptemplate_body_attributes($is_front, $layout, $logged_in); ?>>

and:

function phptemplate_body_attributes($is_front = false, $layout = 'none', $logged_in = false) {
  if ($is_front) {
    $body_id = $body_class = 'homepage';
  }
  else {
    // Remove base path and any query string.
    global $base_path;
    list(,$path) = explode($base_path, $_SERVER['REQUEST_URI'], 2);
    list($path,) = explode('?', $path, 2);
    $path = rtrim($path, '/');
    // Construct the id name from the path, replacing slashes with dashes.
    $body_id = str_replace('/', '-', $path);
    // Construct the class name from the first part of the path only.
    list($body_class,) = explode('/', $path, 2);
  }
 
  $body_id = 'page-'. $body_id;
  $body_class = 'section-'. $body_class;

  if ($logged_in) {
$body_class .= ' user-in'; 
  } else {
    $body_class .= ' user-out';
  }

  return " id="$body_id" class="$body_class"";
}

jcm55’s picture

$body_id and $body_class should be run through filter_xss() calls before they're used -- otherwise you can introduce cross-site scripting vulnerabilities with this.