Building a new theme for Drupal 7

Create a custom look and feel for your Drupal site

A theme accounts for the user interface (UI) of a Drupal website. Even though the theme structure has not changed appreciably, Drupal version 7 comes with a new theme implementation methodology. This article shows how to create a new Drupal 7 theme.

The objective of a Drupal theme is to separate the processing logic of the framework from the design element. For this, Drupal employs a complex theme system that consists of themes, theme engines, and hooks. The theme components work together with the Drupal core systems and modules design elements to create the distinctive look and feel of the user interface—the individual Drupal page and forms. By separating Drupal's business logic from its presentation logic, the code is easier to maintain and you can swap out the implementation of the theme layer without having to rewrite the code layer and vice versa. Figure 1 illustrates the Drupal framework architecture.

Figure 1. The Drupal framework architecture
Graphic representation of the Drupal framework architecture
Graphic representation of the Drupal framework architecture

Themes display data that the Drupal core fetches from the database through an underlying theme engine, which acts as an interface between the Drupal core and the theme templates.

The theme engine

Theme engines are the means through which themes interact with the Drupal core. There are several theme engines that you can use with Drupal. The most popular are:

  • PHPTemplate
  • XTemplate
  • Plain PHP
  • Smarty Engine

You can also use your own custom engine, if you wish.

The PHPTemplate theme engine, which is the default Drupal engine and the one used in this article, uses individual theme files with names like filename.tpl.php to theme Drupal's theme_filename() functions. Each of these files contains an HTML skeleton as well as PHP statements for the dynamic data. Thus, with a basic knowledge of PHP, it is easy to create advanced themes with PHPTemplate because only small bits of code are involved.

Planning the theme

The theme is made up of several files. Just how many files depends on the complexity of the theme. A theme can have just three files or several dozen, including graphic elements and various scripts placed in several folders within the theme directory. Figure 2 shows the typical file descriptions (color, images, logo, templates, stylesheets, and PHP files) that you can expect to find within a theme's main folder.

Figure 2. Typical contents of a theme folder
Screen capture showing the typical folders and files in a theme folder
Screen capture showing the typical folders and files in a theme folder

Not all of these files are necessary in a theme, and some themes don't even have the cascading stylesheet (CSS) file that many think is absolutely required. By understanding how these theme files are used, the structure of a theme and how it works becomes clearer. Let's look again at some of the files in the theme directory and examine their function within the overall theme.

The .info file

The .info file is a required file: It must be included for Drupal to see your theme. The .info files tells Drupal the internal name of the theme. If, for example, the name of this file is, then the name that Drupal gives to this theme will be ibmtheme. If your theme uses such elements as JavaScript, metadata, stylesheets, or block regions, you must also define them in the .info file. Everything else is optional. The contents of the .info file for the Bartik theme, in Listing 1, illustrates this behavior.

Listing 1. Contents of the Bartik theme .info file
; $Id:,v 1.5 2010/11/07 00:27:20 dries Exp $

name = Bartik
description = A flexible, recolorable theme with many regions.
package = Core
version = VERSION
core = 7.x

stylesheets[all][] = css/layout.css
stylesheets[all][] = css/style.css
stylesheets[all][] = css/colors.css
stylesheets[print][] = css/print.css

regions[header] = Header
regions[help] = Help
regions[page_top] = Page top
regions[page_bottom] = Page bottom
regions[highlighted] = Highlighted

regions[featured] = Featured
regions[content] = Content
regions[sidebar_first] = Sidebar first
regions[sidebar_second] = Sidebar second

regions[triptych_first] = Triptych first
regions[triptych_middle] = Triptych middle
regions[triptych_last] = Triptych last

regions[footer_firstcolumn] = Footer first column
regions[footer_secondcolumn] = Footer second column
regions[footer_thirdcolumn] = Footer third column
regions[footer_fourthcolumn] = Footer fourth column
regions[footer] = Footer

settings[shortcut_module_link] = 0

; Information added by packaging script on 2011-01-05
version = "7.0"
project = "drupal"
datestamp = "1294208756"

The .tpl.php template files

The theme directory contains several template files with names such as xxx.tpl.php. These are template files that contain the Extensible HTML (XHTML) markup and PHP variables for the theme. In certain cases, you can code them to deliver other types of data output, such as RSS. Generally speaking, each Drupal theme .tpl.php file is coded to handle specific data outputs: It can be confusing and counterproductive to embed complex logic in template files, as doing so can make them difficult to maintain. The desirable scenario is to have them contain nothing more than straight XHTML tags and PHP variables.

Listing 2 shows the contents of the node.tpl.php file, which describes the output of the basic node for the core Garland theme.

Listing 2. Contents of Garland theme node.tpl.php file
// $Id: node.tpl.php,v 1.24 2010/12/01 00:18:15 webchick Exp $
<div id="node-<?php print $node->nid; ?>" 
  class="<?php print $classes; ?>"<?php print $attributes; ?>>

  <?php print $user_picture; ?>

  <?php print render($title_prefix); ?>
  <?php if (!$page): ?>
    <h2<?php print $title_attributes; ?>><a href="<?php 
       print $node_url; ?>"><?php print $title; ?></a></h2>
  <?php endif; ?>
  <?php print render($title_suffix); ?>

  <?php if ($display_submitted): ?>
    <span class="submitted"><?php print $submitted ?></span>
  <?php endif; ?>

  <div class="content clearfix"<?php print $content_attributes; ?>>
      // Hide the comments and links now so you can render them later.
      print render($content);

  <div class="clearfix">
    <?php if (!empty($content['links'])): ?>
      <div class="links"><?php print render($content['links']); ?></div>
    <?php endif; ?>

    <?php print render($content['comments']); ?>


The template.php file

The template.php file typically holds all the conditional logic and data processing for the output of a theme. You can also use the template.php file to keep the .tpl.php files for the theme uncluttered. Because this is a PHP file, it's mandatory to start the content with a PHP opening <?php tag, but you can omit the closing tag.

Other files

Several other elements are not required for the theme to function but might appear in many themes. These elements include the logo and screen capture, the theme-settings.php file, and files:

  • The logo and screen capture. These elements are recommended but not absolutely necessary for the theme to function. However, if you want to contribute your theme to the Drupal repository, a screen capture is mandatory. Figure 3 is a screen shot for the Garland theme.
    Figure 3. Screen shot of the Garland theme
    Screen capture of the Garland theme
    Screen capture of the Garland theme
  • theme-settings.php. This file displays the administrative UI settings or advanced features beyond general settings such as those for search or the mission logo. A look at the contents of this file for the Garland theme, shown in Listing 3, gives you an indication of what it should eventually display.
    Listing 3. Contents of Garland theme-settings.php file
    // $Id: theme-settings.php,v 1.3 2010/09/04 15:21:09 dries Exp $
     * @file
     * Theme setting callbacks for the garland theme.
     * Implements hook_form_FORM_ID_alter().
     * @param $form
     *   The form.
     * @param $form_state
     *   The form state.
    function garland_form_system_theme_settings_alter(&$form, &$form_state) {
      $form['garland_width'] = array(
        '#type' => 'radios',
        '#title' => t('Content width'),
        '#options' => array(
          'fluid' => t('Fluid width'),
          'fixed' => t('Fixed width'),
        '#default_value' => theme_get_setting('garland_width'),
        '#description' => t('Specify whether the content will wrap to a fixed 
           width or will fluidly expand to the width of the browser window.'),
        // Place this above the color scheme options.
        '#weight' => -2,

    The eventual display will be a form that resembles Figure 4.

    Figure 4. The theme settings page
    Screen capture of the theme settings page
    Screen capture of the theme settings page
  • The function of the color. module is to permit administrators to completely alter a theme's color scheme without having to manually work on the stylesheets. If your theme requires color module support, you must include a color directory with a file together with the various support files.

Building the theme

There are two basic methods for building a theme: You can build it from scratch, or you can modify an existing theme. In this article, you are building a new theme from scratch. That said, though, you'll keep the contents of existing themes handy for the purpose of seeing what the structure looks like.

Creating the directory structure

First, create a directory to contain the theme files. The best place to put this directory is in the sites/all/themes directory. Give the directory a unique name that describes your theme: This name should have no spaces.

Although not compulsory, it helps to create subdirectories for the stylesheet (CSS files), images, and scripts (if your theme uses them). Doing so helps keep things organized.

Building the .info file

The .info file is just a text file containing data—typically, parameters needed to describe the structure as well as the content and configuration of the theme. Inside this text file, each line pairs a key to a value, with the value on the right and the key to the left of the equal sign (=). Listing 4 provides an example.

Listing 4. Sample content from the Garland theme's .info file
; $Id:,v 1.10 2010/11/07 00:27:20 dries Exp $
name = Garland
description = A multi-column theme that can be configured to modify colors and
   switch between fixed- and fluid-width layouts
package = Core
version = VERSION
core = 7.x
stylesheets[all][] = style.css
stylesheets[print][] = print.css
settings[garland_width] = fluid

; Information added by packaging script on 2011-01-05
version = "7.0"
project = "drupal"

You add comments by using semicolons (;) at the beginning of a line. Square brackets ([]), when used, are for creating arrays of associated values. Let's go through the elements that must or can be included in a .info file.


The name value is required. It should be a human-readable name that must start with an alphabetic character. The name has the same limitation for forming functions in PHP, because Drupal uses it for the same purpose. Therefore, the name can contain numbers and underscores (_) but not hyphens (-), spaces, or punctuation. Here is the syntax:

name = Garland


The description key is recommended and should be just a brief description of the theme. The description you enter here appears on the theme select or Appearance page. Here's the syntax:

description = A multi-column theme that can be configured to modify colors
   and switch between fixed- and fluid-width layouts


The screenshot key is optional. Its function is to tell Drupal where to find the thumbnail image of your new theme. The thumbnail image will also be displayed on the Appearance page. If you don't include this key in the .info file, Drupal will call a default screenshot.png file from the default theme's directory. If you have decided to call your thumbnail file a name other than screenshot.png or if you place the file in a directory outside the main directory of your theme, you will need to include this key. Here's the syntax:

screenshot = /images/screenshot.png

To create a screenshot, simply capture an image of your completed theme in a browser. Then, crop and resize the image to a dimension of 294 x 219 pixels, and save it as screenshot.png. Put this file in the same folder as your .info file.


Even though many of the popular themes include the version key, its use is discouraged. If you intend to host your theme in the Drupal themes repository, there is no need to include version, because when a release is packaged for download, automatically adds the version string. Otherwise, you can include whatever version string catches your fancy. Here's the syntax:

version = 1.0


The core key is a required value. In all presently supported Drupal versions, you must indicate the version of Drupal with which your modules and themes are compatible. The value you set here will be compared with the Drupal Core Compatibility constant (found in the include/ file); if no match is found, Drupal will disable the theme. Here is the syntax for the constant:


The packaging scripts automatically set this value based on the Drupal core compatibility setting on each release node (if you are contributing your theme).


The engine key indicates the sort of theme engine your theme uses. It is required in most cases. If you supply no engine in the .info file, Drupal assumes that the theme is a stand-alone theme implemented with a .theme file. Most of the themes found in the repository use the default PHPTemplate engine, which is packaged with the Drupal core. Here is the syntax:

engine = phptemplate

Base theme

If your theme is a sub-theme to another, be sure to declare its base theme to enable theme inheritance. In other words, the file resources from the base theme will be available for use in the sub-theme. You will need to enter the base theme's internal machine-readable name. Here is the syntax:

base theme = garland


The regions key defines the block regions available to the theme. You must specifically define the regions key, and then the internal machine-readable name in square brackets. Then, you must define the human-readable name as the applicable value. Here's the syntax:

regions[highlighted] =Mission Statement

If you chose to define no region, the following values are assumed for a Drupal 7 theme:

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

You can override these values for your specific needs. If you do so, you must declare the line. Here is the syntax:

regions[highlighted] =Mission Statement


You can toggle various page elements on the theme's configuration page. The check boxes displayed on the configuration page of the theme are controlled by the features key (see Figure 5). Thus, you can suppress check boxes for elements that a theme does not define or use. Omitting an entry suppresses a check box for that feature; if you do not define any features, then all the check boxes will be displayed as assumed defaults.

Figure 5. The theme features setting page
Screen capture of the check boxes on the theme features setting page
Screen capture of the check boxes on the theme features setting page

Listing 5 shows all available elements for the features key.

Listing 5. Theme features entry in .info file
features[ ] = logo
features[ ] = name
features[ ] = slogan
features[ ] = node_user_picture
features[ ] = comment_user_picture
features[ ] = favicon
features[ ] = main_menu
features[ ] = secondary_menu


Drupal themes used to default to using style.css. However, in current versions, themes no longer default to style.css if that file is not specified in the .info file. Also, you can add new stylesheets through the .info file. Here's the syntax:

stylesheets[all][] = css/style.css
stylesheets[print][] = css/print.css


It used to be common to include JavaScript files by just calling a function such as drupal_add_js() in the theme's template.php file. However, in Drupal 7, script.js is included only if you specify it in the .info file. Here's the syntax:

scripts[] = scripts/myscript.js


The string that you define here will be the minimum PHP version that the theme supports. The default value derives from the DRUPAL MINIMUM PHP constant (located in the includes/ file):

define('DRUPAL_MINIMUM_PHP', '5.2.4')

You can change this value, but adding the string is not required. Here's the syntax:

php = 5.2.4

Default .info values

The .info file contains default values that Drupal assumes for every installed theme. If these values are not defined in the .info file, Drupal forces the theme to use the default values. Note, however, that these values apply as a group. This means that if you override a line such as:

regions[sub_header] = Sub-header

you will need to redefine the rest of the default regions; otherwise, they will be omitted. This rule also applies to stylesheets. Even though stylesheets are not technically defined in a group, if you define another stylesheet in the .info file, you must again redefine style.css; otherwise, it will not be included.

The keys and values in Listing 6 are the defaults for a Drupal 7 theme.

Listing 6. Default .info values
regions[sidebar_first]  = Left sidebar
regions[sidebar_second] = Right sidebar
regions[content] = Content
regions[header] = Header
regions[footer] = Footer
regions[highlighted] = Highlighted
regions[help] = Help
regions[page_top] = Page Top
regions[page_bottom] = Page Bottom

engine = phptemplate

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

screenshot = screenshot.png

Building the page.tpl.php file

Now, examine the contents of a typical page.tpl.php file. The image in Figure 6 is from the Garland theme and shows what the source looks like in a browser.

Figure 6. The page.tpl.php source code in a browser
Screens capture of the page.tpl.php source code in a browser
Screens capture of the page.tpl.php source code in a browser

When you look more closely, the page.tpl.php template is just a simple HTML page with a large sprinkling of PHP statements. Quite conveniently, most of the PHP elements have already been defined for Drupal, and all you need to do is place them as you wish.

Note: The link [Core Templates] takes you to a list of available variables for the page.tpl.php template.

Adding variables to the basic page elements

Several variables are available for building a page.tpl.php. Which you chose to include depends on the functionality you want to achieve in your theme. For example, if you chose to have breadcrumb trails on your pages, add the $breadcrumbs variable.

The most common variables you will find in the page.tpl.php are:

  • $site_name
  • $logo (the logo uploaded through the theme settings; only useful when you implement the logo theme feature)
  • $title (the page title)
  • $main_menu
  • $secondary_menu
  • $breadcrumbs (a navigation aid that leaves a trail of reference links when a user delves deeper into a website)

There are also variables associated with Drupal administration:

  • $tabs (menu used for editing or viewing admin menus, among other things; often used by modules)
  • $messages
  • $action_links

And some other useful variables are:

  • $base_path (the path to your site root)
  • $front_page (the path to the site front page)
  • $directory (the path to your theme)

You insert variables using the Render application programming interface (API), like this:

<?php print render($tabs); ?>

If your PHP and HTML skills are above average, you can obviously create a champion theme by observing how the example was built, and then using the permitted variables to create your own.

Building other template files

Default templates for other theme files are available and come with the Drupal core. You can find a list of them at the Drupal site (see Related topics for a link). As for the page.tpl.php file, the best way to easily build your own is to find a core file, observe how it was put together, and then build your own. A trip to the Drupal site will point you to the permitted variables for use in any theme file.

The style.css file

In a regular static HTML page, you must include a pointer within the page header to show the location of the stylesheet to be used for the page display. A pointer looks like this:

<link rel="stylesheet" type="text/css" href="/model.css" />

As already discussed, you can add new styles to a theme and overwrite default styles. In both cases, you must enter the theme stylesheet in the .info file. What goes into the stylesheet? You use the same sort of modular approach to CSS classes that the Drupal core uses for standard page elements of the framework. Even though theme developers create their own, a number of classes occur throughout a Drupal site. For a complete list of classes in the Drupal 7 core, see Related topics.


This article gave you an overview of how the theme system functions in Drupal 7. It explained the various components of a Drupal theme and how to proceed with the construction of a new theme from scratch using the default PHPTemplate theme engine. You saw the typical structure of each component theme file. You should have what you need to create your own custom theme. Enjoy!

Downloadable resources

Related topics

Zone=Open source, Web development
ArticleTitle=Building a new theme for Drupal 7