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
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.
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:
PHPTemplateXTemplate- 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.
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
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 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 ibmtheme.info, 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: bartik.info,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 drupal.org packaging script on 2011-01-05 version = "7.0" project = "drupal" datestamp = "1294208756" |
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
<?php
// $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; ?>>
<?php
// Hide the comments and links now so you can render them later.
hide($content['comments']);
hide($content['links']);
print render($content);
?>
</div>
<div class="clearfix">
<?php if (!empty($content['links'])): ?>
<div class="links"><?php print render($content['links']); ?></div>
<?php endif; ?>
<?php print render($content['comments']); ?>
</div>
</div>
|
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.
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 color.inc 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
- 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<?php // $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
- color.inc. 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 color.inc file together with the various support files.
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.
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: garland.info,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 drupal.org 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, drupal.org 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/bootstrap.inc file); if no match is found, Drupal
will disable the theme. Here is the syntax for the constant:
<?php
define('DRUPAL_CORE_COMPATIBILITY', '7.x')
?>
|
The drupal.org 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 Drupal.org repository use the default
PHPTemplate engine, which is packaged with the
Drupal core. Here is the syntax:
engine = phptemplate |
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
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/bootstrap.inc file):
<?php
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 |
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
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
http://drupal.org/node/190815 [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.
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 Resources 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.
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 Resources.
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!
Learn
- Visit the Drupal site to find the default templates for other themes included with the Drupal core.
- Check out the page.tpl.php reference page for a list of variables for use in your theme.
- See the Drupal site for a complete list of CSS classes.
- The Open Source developerWorks zone provides a wealth of information on open source tools and using open source technologies.
- developerWorks Web development specializes in articles covering various web-based solutions.
- Stay current with developerWorks technical events and webcasts focused on a variety of IBM products and IT industry topics.
- Attend a free developerWorks Live! briefing to get up-to-speed quickly on IBM products and tools, as well as IT industry trends.
- Watch developerWorks on-demand demos ranging from product installation and setup demos for beginners, to advanced functionality for experienced developers.
- Follow developerWorks on Twitter, or subscribe to a feed of Linux tweets on developerWorks.
Get products and technologies
- Get more information on Drupal 7.
- Evaluate IBM products in the way that suits you best: Download a product trial, try a product online, use a product in a cloud environment, or spend a few hours in the SOA Sandbox learning how to implement Service Oriented Architecture efficiently.
Discuss
- Check out developerWorks blogs and get involved in the developerWorks community.
- Get involved in the developerWorks community. Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.

Timi Ogunjobi is an author and web applications developer. He is CEO of Xceedia Limited, a software engineering firm with interest in web and mobile applications. He is also the author of three Drupal books amongst several others. You can reach Timi at timi@xceedia.co.uk.




