Quick question gang,

I am trying to make some changes to the css of a specific page on my site. How do I go about doing that? I know that I can create a specific page-name.tpl, but let's say I want to give the page a different background color, how do I go about doing that?

Comments

gforce301’s picture

2 ways I can think of easily are:

1) Give different class names and id's to the elements in your "page-name.tpl". Then you can have css rules in your style sheet to style them differently.

2) Tell Drupal to load an additional style sheet for that page by using drupal_add_css in your "page-name.tpl". You can then override styling rules or add new ones to change the way the page looks.

dnewkerk’s picture

The best way is to cause Drupal to generate unique CSS classes for <body> based on the path of the page. You can then simply add a CSS rule like body.page-1 .whatever and body.page-2 .whatever

The code to do this comes from Zen theme (it's also common in many other themes). Since a few slight modifications are needed to convert Zen's code for general use, below is the modified code, which you can simply copy and paste into your theme.

1) Locate the <body> tag in your page.tpl.php template, and replace it with <body class="<?php print $body_classes; ?>">

2) Open (or create if you don't have one) your template.php file. Use the "Find" feature of your code editor to search for "preprocess_page". If you find anything, then you will need to merge the code rather than just paste in the whole thing (more on that later). If you find nothing, then you can simply copy and paste this code into your template.php:

function phptemplate_preprocess_page(&$vars, $hook) {
  // Classes for body element. Allows advanced theming based on context
  // (home page, node of certain type, etc.)
  $body_classes = array($vars['body_classes']);
  if (!$vars['is_front']) {
    // Add unique classes for each page and website section
    $path = drupal_get_path_alias($_GET['q']);
    list($section, ) = explode('/', $path, 2);
    $body_classes[] = phptemplate_id_safe('page-' . $path);
    $body_classes[] = phptemplate_id_safe('section-' . $section);
    if (arg(0) == 'node') {
      if (arg(1) == 'add') {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-add'; // Add 'section-node-add'
      }
      elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-' . arg(2); // Add 'section-node-edit' or 'section-node-delete'
      }
    }
  }
  $vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}


/**
 * Converts a string to a suitable html ID attribute.
 *
 * http://www.w3.org/TR/html4/struct/global.html#h-7.5.2 specifies what makes a
 * valid ID attribute in HTML. This function:
 *
 * - Ensure an ID starts with an alpha character by optionally adding an 'id'.
 * - Replaces any character except A-Z, numbers, and underscores with dashes.
 * - Converts entire string to lowercase.
 *
 * @param $string
 *   The string
 * @return
 *   The converted string
 */
function phptemplate_id_safe($string) {
  // Replace with dashes anything that isn't A-Z, numbers, dashes, or underscores.
  $string = strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
  // If the first character is not a-z, add 'n' in front.
  if (!ctype_lower($string{0})) { // Don't use ctype_alpha since its locale aware.
    $string = 'id' . $string;
  }
  return $string;
}

If your theme's template.php already has a preprocess_page function, you need to merge the code into it. A code editor (such as Komodo Edit) with start/end { } highlighting should help make that pretty simple.

  // Classes for body element. Allows advanced theming based on context
  // (home page, node of certain type, etc.)
  $body_classes = array($vars['body_classes']);
  if (!$vars['is_front']) {
    // Add unique classes for each page and website section
    $path = drupal_get_path_alias($_GET['q']);
    list($section, ) = explode('/', $path, 2);
    $body_classes[] = phptemplate_id_safe('page-' . $path);
    $body_classes[] = phptemplate_id_safe('section-' . $section);
    if (arg(0) == 'node') {
      if (arg(1) == 'add') {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-add'; // Add 'section-node-add'
      }
      elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-' . arg(2); // Add 'section-node-edit' or 'section-node-delete'
      }
    }
  }
  $vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces

Also add this part separately outside of the preprocess_page function, to the bottom of your template.php:

/**
 * Converts a string to a suitable html ID attribute.
 *
 * http://www.w3.org/TR/html4/struct/global.html#h-7.5.2 specifies what makes a
 * valid ID attribute in HTML. This function:
 *
 * - Ensure an ID starts with an alpha character by optionally adding an 'id'.
 * - Replaces any character except A-Z, numbers, and underscores with dashes.
 * - Converts entire string to lowercase.
 *
 * @param $string
 *   The string
 * @return
 *   The converted string
 */
function phptemplate_id_safe($string) {
  // Replace with dashes anything that isn't A-Z, numbers, dashes, or underscores.
  $string = strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
  // If the first character is not a-z, add 'n' in front.
  if (!ctype_lower($string{0})) { // Don't use ctype_alpha since its locale aware.
    $string = 'id' . $string;
  }
  return $string;
}

If nothing happens, you may need to clear the theme registry. Visit the Themes page of your site and submit it with no changes (quick way to clear the theme registry). I always recommend this method over page-something.tpl.php if possible. I suggest only using different page templates if you absolutely must have completely different HTML and can't accomplish it with CSS). Having multiple page templates can get difficult to maintain if you make changes (if they're all basically the same page, you have to apply the same changes to all of them every time you change anything).

-- David
davidnewkerk.com | absolutecross.com
View my Drupal lessons & guides

cmckay’s picture

Thanks for the detailed reply Keyz.

Critical Tinkerer’s picture

Thanks, Keyz, for the detailed steps.

Keyz said:

The best way is to cause Drupal to generate unique CSS classes for based on the path of the page. You can then simply add a CSS rule like body.page-1 .whatever and body.page-2 .whatever

It would be helpful if there were more details or even a recipe on where/how to do this.

For example, how would I implement different CSS on:

  • a specific node
  • a specific content type (book, forum, page)
  • a custom content type
captain_hook’s picture

this is only specific for the "body'..

just like what hardfocus said:

It would be helpful if there were more details or even a recipe on where/how to do this.

For example, how would I implement different CSS on:

* a specific node
* a specific content type (book, forum, page)
* a custom content type

we need an update to this one..

thanks by the way..

cheers...

Anthony Pero’s picture

I realize this post is almost a year old, but I thought I should put an answer in for forum users searching for them:

The code above adds a "bunch" of classes to your body tag. So, it would add a class to the body tag that included the Node ID. So to theme a specific node you would start your selector with body.node-10 .other-selectors-you-need-to-accomplish-your-goal. Same for a content type; your css selector would start with body.content-page (or whatever the actual class is in the body tag.) Just make your selectors specific enough to override the base styles.

Tony

Anthony Pero
Project Lead
Virtuosic Media
http://www.virtuosic.me/