Drupal 7: Add Node Terms to Body CSS classes

David G - DrupalA typical requirement of many websites I’ve created is to display a particaluar graphic on a section of a website, or Nodes containing a certain field value association. This is used by Designers to give a visual indication of what section of a website a visitor is seeing. By default most Drupal themes do not include this type of functionality enabled by default. Here are 2 approaches to enabling this functionality.

An example of the type of output I’m referring to are these 2 pages of a website. The top banner image of the website will be 1 image for pages within Research and another image within the Undergraduate section of the website:

Example Research banner image.

Example Research banner image.

Example Undergraduate image for section of website.

Example Undergraduate image for section of website.

Approach #1: Use HeaderImage or Views Menu Reference Modules

Both of these modules allow you to create blocks of content that can be displayed within sections of a website. A benefit of using HeaderImage or Views Menu Reference is that you can create a drupal content type to allow site moderators to upload custom images (or assests) to display in blocks on a page.

In the past I’ve written blog posts on both of the above modules, I recommend doing a google search to find my posts on them if you want to empower your end users to place images for sections of a site.

Approach #2: Use a custom theme function and CSS rules

A simpler, yet powerful, way to achieve the same effect is to write some custom code for your subtheme which injects the necessary body classes into your HTML template file.

As an example I use the following code within my subtheme to add classes to the HTML body tag:

 * Implements hook_preprocess_html().
 * Add the taxonomy terms assigned to a node to the body classes.
 * This code taken from http://dropbucket.org/node/777
 * and adopted to the AIM page fields, and more project specific css class names.
function aim_preprocess_html(&$vars) {
  $vars['content_column_class'] = ' class="col-md-8"';
  if (!$vars['is_front'] && arg(0) == 'node') {
    $node = node_load(arg(1));
    $results = field_view_field('node', $node, 'field_section', array('default'));
    foreach ($results as $key => $result) {
      if (is_numeric($key)) {
        // Call drupal_html_class to make safe for a css class (remove spaces, invalid characters)
        $vars['classes_array'][] = "aim-section-term-" . strtolower(drupal_html_class($result['#title']));
        // Add taxonomy ID. This will allow targeting of the taxonomy class even if the title changes
        $vars['classes_array'][] = "aim-section-tid-" . $result['#options']['entity']->tid;
  // Additionally tweak the page column class value for our
  // Bootstrap subtheme if none is found.
  if (!empty($vars['page']['sidebar_first']) || !empty($vars['page']['sidebar_second'])) {
    $vars['content_column_class'] = ' class="col-md-8"';
  else {
    $vars['content_column_class'] = ' class="col-md-12"';

This function uses template_preprocess_html() from my theme to customize how Drupal builds up the HTML it will return to the visting browsers request.

Upon visiting the page the selected term for the Node’s section field is loaded and appended to the existing body classes as both the term name and the term id.

So the generated HTML for the page for example is:

<body class="html not-front not-logged-in one-sidebar sidebar-second page-node page-node- page-node-23 node-type-page navbar-is-fixed-top aim-section-term-research aim-section-tid-2 bootstrap-anchors-processed">

This projects name is AIM internally. So I add body classes of the form aim-section-* to denote that these classes are project specific; they neither come from Drupal core, nor are they generated from any parent theme my site is using.

In some websites I’ve seen this done code only injects the field name, here such as “research” into the body classes and not the value “tid-2” for example. There are pros and cons to this approach. If you allow your client control over the field value(s) used to express the section then they may abritrarily change the value to something new at any time — if you’ve written CSS to target .research for example then your CSS may break and not show the image you want to show per section of the website. While if you use tid-2 in your CSS classes then so long as the term exists the page will continue to show the image regardless of site moderator content updates.

Using the above body classes I can then write LESS or CSS to output preset image(s) per section:

body.page-news-events, body.not-front.page-node {

  // This is a generic page fallback if the image for the term is not found below.
  .leaderboard-region {
    background: url("../images/aim-stripe-image-interior.jpg") no-repeat center;
    min-height: 348px;
    background-size: cover;

  // For this rule add new Taxonomy term sections to the css selector as:
  // .aim-section-term-NAME.leaderboard { ... }
  // or more specific because the name may be changed, use the term-id:
  // .aim-section-tid-TID.leaderboard { ... }
  .aim-section-tid-2.leaderboard-region {
    background: url("../images/aim-stripe-image-interior.jpg") no-repeat center;
    min-height: 348px;
    background-size: cover;

So the above LESS rules state:

  • If we are not on the website frontpage, or we are on a News View page …
  • Show this default banner image on all pages …
  • Unless this generic default banner image is overridden by a more specific tid based rule which follows.

In this fashion any non-front page Drupal page is given a top banner image and the webhost designers can create the images as-needed per section.

Looking for quality web hosting? Look no further than Arvixe Web Hosting!

Tags: , , | Posted under Drupal | RSS 2.0

Author Spotlight

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *