David Needham Guest Trainer
October 16, 2011

In Level 1 we introduce the anatonmy of the theme and the files you'll find within. We walk through creating your own basic theme and introduce the concept of sub-theming.

In the "evolution of a themer", this is where the fun really starts. Up until now you may have downloaded a contributed theme from Drupal.org, maybe you hacked the theme a bit to make it your own but you've never made your own theme. This blog post is all about reaching Level 1 and creating your own basic theme from scratch.

What is a theme?

By definition, a theme is a layer in Drupal which styles and formats your output right before it's put on the screen. The theme gives you one last chance to change something before your visitors see it. Themers have ultimate control of the website because they're in control of that output.

It's my personal opinion that a theme is a thing of beauty and inspiration. In a sense, themes are art that should never have boring names like "example" or "demo", so consider naming your new theme something interesting. Because this theme is going to be rebuilding our training theme, we'll be calling the theme "Acme". Anywhere you see Acme, assume that you can insert the name of your own theme instead.

Theme Anatomy

Both contributed and custom themes exist in the /sites/all/themes directory - each within their own folder. We'll call our folder "acme". Right now we just have an empty folder, but here's what many existing themes look like:

Inside every theme is a .info file. Typically you'll also find styles (.css files), templates (.tpl.php files), javascript (.js files), images and an ambiguously named template.php file. Here's a brief explanation of some of the most common files you should see in the image above.

  • acme.info - The .info file of the theme identifies all of the important information that Drupal needs to know about the theme including name, description, the Drupal version it's compatible with, where your stylesheets are, what regions you want and a lot more. The .info file is dissected below.
  • style.css - You put all of your CSS code (styles) into .css files (stylesheets). You may use as many or as few stylesheets at you want. Typically I use a .css file that uses the name of the theme (acme.css) for most of my styles. It's also fairly common to see a layout.css, text.css or reset.css - each broken down to be used for their individual purpose. You can call the file whatever you want, just make sure you define it in the .info file.
  • page.tpl.php - In Drupal, any file that ends in .tpl.php is a template file. We'll cover these later.
  • utilities.js - I don't find myself using a ton of javascript or jQuery, but when I do it's in the theme. You can call the file whatever you want, just make sure you define it in the .info file.
  • template.php - This is where all of the PHP magic happens. If you don't know PHP, don't be intimidated by template.php - just google what you want to do, find a code snippet from where someone else did it, paste it into template.php and change the name of the function to include your theme instead of their example theme.

You may put these files in folders to help keep your theme folder tidy if you wish, but none of the folders are required. I typically have folders for styles, images and templates.

Creating the initial files and structure

  1. If you haven't already, navigate to "sites/all/themes" and create a folder called "acme".
  2. Create your acme.info file to help Drupal identify the theme using the example below:


name = Acme
description = A theme by any other name is just boring.
core = 7.x
engine = phptemplate

stylesheets[all][] = styles/acme.css

regions[header] = Header
regions[highlighted] = Highlighted
regions[help] = Help
regions[content] = Content
regions[sidebar_first] = Left sidebar
regions[sidebar_second] = Right sidebar
regions[footer] = Footer
regions[page_top] = Page top
regions[page_bottom] = Page bottom

features[] = logo
features[] = name
features[] = slogan
features[] = node_user_picture
features[] = comment_user_picture
features[] = favicon
features[] = main_menu 
features[] = secondary_menu

The first part should be pretty self explanatory. The only gotcha is that engine = phptemplate. This is one of the things that you should just always add in your .info file. It's true that engine isn't officially required in Drupal 7, but we still include it because some drupal.org users have reported getting errors when they omit it.

Next you must declare all of the stylesheets. The first set of square brackets is where you tell Drupal which media type this stylesheet should be used for (all, screen, print, etc). The second set of square brackets is always blank and should always be included. After that, you tell Drupal where to find that particular stylesheet. (ie. If you have a print stylesheet within a css folder, you'd put stylesheets[print][] = css/print.css.

Next you tell Drupal which regions you will use. The ones you see in this list are the default in Drupal 7. You may completely omit any regions and Drupal will automatically assume that you want all of the default regions. That being said, starting at the point above will help you understand what you have to work with immediately and make it easy to remove/add to the list from there. It's important to note that if you want to use all of the default regions and add one more, you must declare all of the regions and your extra one. If you only declare that one extra region Drupal will assume that you only want that region.

Lastly you declare which features you want to make available on the theme settings page. This is the default list and just like for regions, it's recommended that you start here. Also like regions, Drupal will assume that you want to make available all of the features. As a best practice, when you no longer want to include a feature you should always remove the feature from your .info file.

For example, if you know that you do not ever want the site name printed on the page (maybe your logo already includes it), you should remove the feature from your .info file. You don't know how aggravating it can be to enable a feature only to discover later that the print statement for it was removed from page.tpl.php.

If you do this and save your file, you should now see a new theme in your appearance page! If you enable it, you can see what Drupal looks like without any clothes on (!). It's not pretty, but this is a starting place for everything else! Add in your css, js (if appropriate) and you've got a theme. If you need more help with your .info file, I highly recommend that you check out the Drupal guidebook page on the structure of the .info file.

Tools Themers Use

The more tools the themer has, the more magic they can perform. Here are some of the tools in my theming toolbox (in no particular order):

  • Admin menu - If you're not using the admin menu module, you should be. We use this on every one of our websites without question. It puts (almost) every administrative page one click away, which is a huge time saver.
  • Devel - Devel is used for plenty of developer tasks, but it's great for theming as well! One of the features in devel that I use all the time is Devel Generate, which allows you to generate content on your website so you have something to work with when you start theming. It can use existing content types and fields within, so it's very handy.
  • Theme Developer - This used to be part of Devel but is now it's own module. It's pretty buggy and should never be taken as law, but it helps you identify where something on the page is coming from. What tpl.php is printing the block title? Which function is generating the primary menu? Theme Developer can tell you. This module is very buggy and should only be enabled when you need it. Be aware that it adds extra spans to help outline things on the page, so be careful not to add style to these random spans!
  • Firebug - Anyone who uses html and css should have heard about Firebug by now. It's an add-on in Firefox which helps you select elements on the page and see what styles are affecting it. Not only that, it can tell you which line number that style was added on. It's also used for other developer / administrative tasks like javascript and performance information.
  • Style Guide - There are always things in Drupal which people forget to design or theme for. Do you always remember the status messages or submit buttons? This module gives you a single page that shows you the most commonly themed elements on a page including forms, headers, images and several Drupal-specific things you can theme. I've found it helpful to show this page to designers so that they can create an identical photoshop or fireworks file that outlines each of these elements.


It's a real no-no to modify any core or contributed file in Drupal Sub-themes allow you to say "Hey Drupal! Use this theme, except these changes I'd like to make." That way the original theme stays intact and you're able to quickly make changes without starting over from scratch.

Making a sub-theme is super easy! If you'd like to see how easy it is, just add base theme = garland in your acme.info. Refresh and page and boom, your theme is using all of the files from the Garland theme. Want to make a change to Garland? You can still utilize your stylesheets, or just copy a file from the original Garland theme into your custom theme to have Drupal automatically start using your modified version.

Themes which were created specifically for the purpose of being used with a sub theme is referred to as a "base theme". Base themes can be a huge timesaver because they give you a solid starting point. You don't have to start from scratch (which can be pretty intimidating). Here's a list of common Drupal base themes you can check out:

  • Omega
  • AdaptiveTheme
  • Tao
  • Zen
  • NineSixty (960gs)
  • Fusion (bonus if used with the skinr module)
  • Framework

[This is part 1 of the Leveling Up Your Themer series - a multi-part blog post introducing popular theming topics to help you level yourself up as a themer.

Sign up for the mailing list to be notified when there are new posts in this series and follow @chapter_three on twitter for all of the latest updates!]