How to Make Changes to a Drupal Theme

posted Jun 23, 2011, 9:00 PM by admin@

In this sub-tutorial I’ll be showing how to locate places in your theme’s files controlling different aspects of a Drupal page, how to experiment interactively with changes, and how to finalize those changes. If you are just starting with my tutorials, and new with Drupal, I suggest you visit the link above, it goes to where I give an overview of Drupal customization.

Step Zero: Having a Theme you are Ready To Modify
This is a step by step tutorial, so you should have Drupal installed, and either a contributed theme downloaded from installed that supports local changes, or you’ve created your own sub-theme that is waiting for base theme overrides to create your final theme. If you are unclear what I’m talking about, check out the previous sub-tutorials in this series.

Step One: Getting Your Tools and Workspace Setup
The best method I’ve found for interactive Drupal theme modification uses the Firefox browser and its Firebug plugin. If you do not already have these tools installed, download and install them now.

Since we’ll be working in Firefox, get it running and loaded with a page of the Drupal site using the theme you are ready to modify.

Depending upon your familiarity with CSS, in another Firefox tab you may want to load for quick reference.

Next, you will need a text editor opened with one of two possible files:

  • If you are modifying a theme that supports local changes, you should have your theme’s “local.css” file loaded and ready for editing;
  • If you are working in your own sub-theme, you should have your sub-theme’s overriding CSS file loaded;
  • If you do not fit one of these situations, you should read my description of the choices for Drupal theme modification.

Next, because we will be making changes to aspects of a theme that may be cached by Drupal, in yet another Firefox tab, load up the performance page of the site you are modifying:


On the performance settings page, make sure Caching mode is disabled, Block cache is disabled, and may as well disable both Optimize CSS files and Optimize JavaScript files. The last two should not matter, but with them disabled, they are removed from any possible suspicion during bug hunts. Make sure you click the Save configuration button after making any changes to the page, and then return to the bottom of the page and click the Clear cached data button.  I’m pretty sure saving a new configuration will clear the cache, but clearing the cache explicitly can’t hurt.

Firebug Icon
Check the bottom right of your Firefox browser window for the above icon. That icon appears when you have Firebug installed and activated. If you don’t see that, you should visit Firebug’s FAQ, covering installation and general usage. It probably wouldn’t hurt for people new to Firebug to load that page into another Firefox tab for reference.

Step Two: Using Firebug to find a place you want to change
As an example case, we’ll look at a few changes I did to the Garland sub-theme I created for this web site. One of the first changes I wanted over Garland’s default was a different text color for the content of main articles, (the text used to display nodes.) The text color in Garland is not black; it is medium gray. Text in a medium gray yields a softer appearance, where I would like a crisper, stronger appearance. I would like the font to be black.

In order to figure out what to change to accomplish my text color change, click the Firebug icon at the bottom right of the Firefox browser window. That will cause the Firebug icon to become color, as well as a new sub-window to take over the bottom portion of the browser window. Next, click on the highlighted icon shown below:

Activating Firebug's Element Inspector

That icon enables Firebug’s Element Inspector. Now as you move your mouse over the Drupal page, you will see blue rectangles outline each element as your mouse passes over. Additionally, the left and right portions of the Firebug sub-window update:

Using firebug's Element Inspector to examine the text on a page

While using the Element Inspector, the left side of the Firebug sub-window shows the current page’s HTML, with the HTML markup generating the blue outlined element also highlighted in blue. On the right side of the Firebug sub-window is the CSS code controlling the display of the highlighted page element. There is some additional very useful information here, so I’ve identified more key places for you:

Key information given by Firebug's Element Inspector

On the right side of the above Firebug sub-window, outlined in purple are two places where Firebug gives the line number and CSS filename controlling the highlighted page element. This right side is a hierarchical display, with the top CSS element being the “leaf” CSS declaration affecting the selected page element. Each CSS declaration moving down in the right handed side of Firebug’s display is the parent CSS declaration of the CSS element above; together the entire vertical series of CSS declarations is the CSS hierarchy affecting the selected page element.

On the left side of the above Firebug sub-window is outlined in orange where Firebug shows the nesting of CSS and HTML elements for the selected page element. Not to be confused with the hierarchy of the CSS definition, this is the nesting of HTML and CSS on the web page, showing you how the HTML references the CSS used to create the page.

To help illustrate the nesting of the CSS elements, here is what Firebug gives for the above:

p < < div.left-corner < div.right-corner < div#squeeze …

This tells you that for the selected page element (in my case, the main text of a Drupal page):

  • The inner most controlling tag is a “p” tag,
  • The next inner most controlling tag is a “div” tag with a class of “help”,
  • The next inner most controlling tag is a “div” tag with a class of “left-corner”,
  • The next inner most controlling tag is a “div” tag with a class of “right-corner”,
  • The next inner most controlling tag is a “div” tag with an id of “squeeze”.

This information is useful to create nested CSS declarations that only affect the CSS used on a specific page. We’ll get to use such information a bit later. At the moment, we’ll focus on a simple change, changing the font color.

Looking back at the right side of the Firebug display, there are two CSS elements controlling a node’s main text: the CSS declarations for the “p” and “body” tags:

Firebug showing the color defined by a CSS declaration

As you move your mouse over the body tag’s color definition, you’ll notice hovering over a color declaration causes a small rectangle filled with the same color to popup as visual reference. Likewise, you can click on any of the CSS commands or parameters and make changes. You can click on a single parameter, and once your edit cursor is beating on that parameter, the up and down keys increment and decrement the parameter – if the parameter is numerical, it adds and subtracts one to the parameter; if the parameter is text, up and down keys move you through a list of possible parameter values. You can also right-mouse-click over a CSS declaration and get more editing options. As you make modifications, the web page updates automatically to show the result of the changes. If you are not in awe over this, you have not been working with technology long. This is so useful, I’m surprised someone has not claimed patent ownership and wrapped this up behind paywalls!

Step Three: Creating Overriding CSS to Change the Theme
Continuing with the goal of changing the font color, we can see from the above that our main content’s font color definition is on line 15 of the file “style.css”. However, in my theme I have no “style.css” file – that file is in my base theme’s directory. It is one of the inherited properties from my sub-theme’s base theme.

When working in a theme that supports local changes, the situation is very similar: the originating definition lies in a file other than the “local.css” file all your changes should be placed.

In order to override the color definition, I used the following:

a) Inside my theme’s “GarlandSub.css”, I entered the following at the bottom of the file:

/* making node font black: */ 
body {
  color: rgb(0,0,0);

b) Saving the above, I return to the web browser and click the “refresh” button to reload the same web page. Sure enough, the text is now darker!

c) If you are following these steps and the web page refreshes to the same font color as before, revisit the other tirefox tab where I suggested you keep admin/settings/performance loaded, and click the Clear cached data button at the bottom of the page. Now try refreshing the web page again to check if the text color changed.

d) If you are still not seeing the correct text color, try re-enabling Firebug’s Element Inspector and mouse over the element you are trying to change; in my case it is the text in a typical Drupal page.

Firebug showing the new CSS, overriding the previous color declaration in another file

You can see in the above image how my new CSS is working: there is now a new overriding “body” tag being used, from the file “garlandsub.css”, and it defines the text color as all zeros – which is the color black.

If you are not seeing something similar, then your CSS change is not being recognized and picked up…

Before resorting to “drastic measures”, verify the theme you are trying to change is the current default and enabled theme at admin/build/themes. Also verify that you are editing the correct CSS file. Once again, try the browser's refresh button to reload the Drupal page and see if your change is being picked up.

e) If that still is not showing you the changed color, try clearing your web browser’s cache. I hate going to that extreme, because any web site’s I’m logged into gets their session ids cleared, and I need to re-login.

f) No doubt, some of you will still not see the desired CSS change, even after verifying and re-following the steps. There are more steps you can take to track down the cause of your changes not being picked up, but that detours the tutorial into a troubleshooting guide. Expect another tutorial soon covering additional steps. (Hint: try other browsers and the Firebug Lite java script file.)

A quick summary of the key steps involved in modifying one element in a theme's CSS:

First identify the CSS controlling the element you want to change with Firebug’s Element Inspector:

Firebug's Element Inspector icon

Next test the desired change by interactively modifying the selected element’s CSS via Firebug’s display of the selected element’s definition within its CSS hierarchy:

Firebug's interactive editing of a CSS declaration

Then create a new CSS declaration in your overriding CSS file; that file is named “your-theme-name.css” for those working with their own themes or sub-themes, and is named “local.css” for those working with a theme  supporting local changes:

New CSS placed inside the overriding CSS file

And finally, reload the web page containing the modified element(s), with possible cache clearing as necessary to see your intended change.

The above steps work great in cases where the desired change  is universal, such as the color of text used for all nodes. However, the above is the rare case; more often the change needed is not universal, it is specific to one element on one page or one class of elements used in multiple pages, but not for all pages.

For the next example, I will show how the information Firebug provides on the left side of its sub-window can be used to solve the remaining cases not quite as simple as our first example. Keeping the complexity at minimum, the next change I will show is how to place a border around all inline images within nodes.

The first step in this new example is to either create or navigate to a page of my site where I have images both inline within a node’s content, as well as images not in a node’s content, such as in a block. My goal is to modify the display of all images inline to nodes, while leaving all other images alone. Finding such a page, I realize it has three different types of images: those inline in a node, images in blocks, as well as the web site’s logo image up in the page header.

The next step is to enable Firebug’s Element Inspector and take a look at our images:

(click to enlarge) Firebug's Element Inspector looking at the site logo in the page header

(click to enlarge) Firebug's Element Inspector looking at an image in a block

(click to enlarge) Firebug's Element Inspector looking at an image inside a node

Looking at the top left area of each image, where Firebug gives the nesting of CSS and HTML elements for the selected page element, you’ll see each image is described quite differently:

  • Web site logo: the “img#logo” left most tag is telling you the logo is inside an “img” tag with an id of “logo”; looking lower into the blue highlighted HTML, yes – you can see the HTML markup with an “img” tag followed by id=”logo”.
  • Sidebar-right block image: the left most tag is just a plain “img” tag, which is pretty generic. However, looking into the HTML of the page, we can see all sidebar blocks are enclosed within a “sidebar” class, and each block is enclosed within a “div” given a unique id. That can be used to target CSS image declarations specific to all sidebar images, or all sidebar-right images, or just the images inside a specific block. This is very similar to our goal, but we’re after images inside nodes…
  • Node image: the left most tag here is also a plain “img” tag, just like a block. Looking lower, into the HTML of the page I can see the blue highlighted “img” tag enclosed inside a “p” tag, with that “p” tag enclosed inside a “div” tag with the classes “content” and “clear-block”. The next enclosing tag is a “div” with an id set to “node-17” and a class of “node”.

Now we have all the information we need. We want to change how images are displayed for all nodes, and we just saw that Drupal places nodes inside divs with their id set to “node-number” and with a class of “node”. Loading up a few other nodes to verify, yes – Drupal always puts nodes inside divs with a unique-to-that-node id and a class of “node”.

Going back to our overriding CSS file, I create the following new declaration at the bottom of my GarlandSub.css file:

/* giving images inside node content a gray border: */
.node img {
    border: 1px solid #CECECE;
    padding: 3px; 

The portion of the declaration outside the curly brackets is saying: for all “img” tags inside elements with a class of “node”, use the CSS inside the curly brackets (in addition to any other CSS not overridden by these declarations.) The CSS inside the curly brackets is saying: for this element, use a 1 pixel, solid border with a color of #CECECE, and wrap that border around the element with 3 pixels of padding.

Saving my overriding CSS file, I reload the page… and there I see a nice border around my image, and the image in my block is unaltered, as well as my site logo image is unaltered. Navigating around the site to confirm, yes, this change is isolated to every inline image within a node, while all other images on the pages are unaltered.

As you can see, this is a very direct method of finding the controlling CSS of any page element. Once you have chosen the CSS change or addition, rather than making changes to the originating CSS, we add our changes to an overriding CSS file. Using this workflow, we ensure we can pickup future bug and security fixes for our theme or base theme.

Here is a final example demonstrating how to target a single block with a CSS modification. You probably noticed I have an Amazon ad for my favorite Drupal book in the right sidebar. Beneath the ad is some endorsement text I wrote, which I would like to have displayed with less space than normal between the lines. Remembering from the above examination of images inside a sidebar, I noticed each block receives a unique id; that unique id is what I will use to target my Amazon book ad.

With Firebug’s Element Inspector, I highlight my endorsement beneath the Amazon ad and look for the unique id defining my block:

Firebug's Elment Inspector showing the id & class used for a block

As shown above, the div id of the block is “block-block-1”. Since I’m creating a new CSS declaration, I just add this to my overriding CSS file:

#block-block-1 {
   line-height: 1.1em;

I added the above first with a value of “0.2em”; meaning use a line height equal to 20% of normal. That made my endorsement text appear all scrunched up on top of itself. With Firebug’s Element Inspector I am able to select that bad text and interactively find the line-height setting that looks most pleasing. Copying and saving the final value to my overriding CSS file, the modification is complete.

To facilitate targeting page elements, Drupal generates all elements in the following manner:

  • Class names are general, such as block, sidebar, sidebar-left, sidebar-right, and node
  • Div ids are specific, such as block-block-2, and node-23

This structuring of the tags on a Drupal page provides great control when modifying a theme. Additionally, the Views and Panels modules continue this naming pattern, enabling pages created by Views and Panels to enjoy easy theme modifications.

Optional Step Four: using additional modules supporting theme development
Of course, this only scratches the surface of the theme development techniques available in a Drupal environment. Several Drupal modules support advanced controls for theming, such as:

  • Theme Editor module: provides user interfaces for editing of CSS, “.info”, and template files within a Drupal site; great for people working with remotely hosted Drupal installations.
  • Skinr module: enables a theme to define a set of reusable and modular CSS styles, and make those styles available in Drupal's user interface.
  • Block Theme module: enables an admin to define template files for standard block templates and provides a selection box on the block configure form so the admin can select a template file to use as opposed to having to override the templates by block ID.
  • Themer module: provides controls to dynamically create customized body classes and more.
  • Theme Developer module: provides support for people writing their own template files by showing the template used to generate an element, plus additional features.

The above is just a sample of what is available. As you can see the more advanced theming options also provide support for template development and debugging. (A template file is a mixed PHP and HTML file, used by Drupal to generate the final HTML of a region.) I rarely have the need to modify template files, primarily because I’m more of a “coder” than a “themer”. However, understanding them is invaluable, and knowing when you need to operate at the template level can be essential for competent Drupal development.

We’ve covered a lot of information in this tutorial. If you are new to Firebug, I suggest you work with it for a while first, before you investigate the additional theming support modules I describe above. This concludes the "comprehensive" section of this tutorial on modifying a Drupal theme. Over time I will be adding super-brief tutorials covering useful CSS snippets, such as my first snippet covering how to remove the "homepage" field from the anonymous comment form. If you are interested in learning about the module development, PHP and Java Script side of Drupal, you may want to see my tutorials starting with how to insert and use PHP in your site's content.

If you have any questions or suggestions for how I can improve the above, please write a comment. Constructive comments will be followed as much as possible.