The Drupal 7 Style Guide

The Importance of themes in Drupal

The theme displayed on your Drupal site is the visual appearance of the site. The theme files, or template files as it's often called, control the placement of the elements; mainly regions and blocks, for the purpose of presenting the content and interactivity of a website. How well a theme is designed and implemented is, therefore, largely responsible for the first impression made by those who visit your site. Themes are the most visible, and arguably the most influential, element of your Drupal site. 

While the default Drupal distribution includes a set of themes that will prove sufficient for some users; for the vast majority that simply is not the case. This style guide is for those with the desire to do more; whether it be to customize a theme, create a sub-theme or to build your own themes.

What is a theme?

In the world of Drupal, the term "theme" means a collection of inter-related files that are responsible for the look and feel of a Drupal website. There are many content management systems (CMS) that use different names for these files but the premise is still the same regarding the functionality of a particular system. In Drupal the common term of use is known as a "template."
 
There are many perspectives to look at a Drupal theme:
  • A Drupal theme seen as a container for the purpose of formatting and displaying data
  • A Drupal theme seen is a collection of template files that format data regarding the presentation viewed by its site visitors
  • A Drupal theme seen for cosmetic purposes - how your site looks.
When constructing a Drupal theme many types of files that are familiar to web designers that includes stylesheets, images, and JavaScript are all rested within a theme folder within your site's hierarchy. A theme may also include some files whose extensions may not be so familiar, for example *.tpl.php files – an extension that is used to designate template files that use the default PHPTemplate theme engine supplied with Drupal.

The Theme

A theme is the outer shell of a Drupal site. It consists of a single folder with PHP, CSS, images, and possibly JS files. These files work together with Drupal to make your site function and look great.
 
A good Drupal Theme CSS arsenal may include:
  • A reset stylesheet - that sets a default CSS across all web browsers thus creating a standard we can work from
  • Fonts with rem (root em) units so that they are easily adaptable
  • Simple responsive navigation menu for small screens.
  • A stylesheet with major selectors included

Required files:

To create a theme that uses the PHPTemplate theme engine, you need three files:
  • page.tpl.php: The file containing the regions and the key elements of the layout. The default Drupal page.tpl.php looks like this:
<?php

/**
 * @file
 * Default theme implementation to display a single Drupal page.
 *
 * The doctype, html, head and body tags are not in this template. Instead they
 * can be found in the html.tpl.php template in this directory.
 *
 * Available variables:
 *
 * General utility variables:
 * - $base_path: The base URL path of the Drupal installation. At the very
 *   least, this will always default to /.
 * - $directory: The directory the template is located in, e.g. modules/system
 *   or themes/bartik.
 * - $is_front: TRUE if the current page is the front page.
 * - $logged_in: TRUE if the user is registered and signed in.
 * - $is_admin: TRUE if the user has permission to access administration pages.
 *
 * Site identity:
 * - $front_page: The URL of the front page. Use this instead of $base_path,
 *   when linking to the front page. This includes the language domain or
 *   prefix.
 * - $logo: The path to the logo image, as defined in theme configuration.
 * - $site_name: The name of the site, empty when display has been disabled
 *   in theme settings.
 * - $site_slogan: The slogan of the site, empty when display has been disabled
 *   in theme settings.
 *
 * Navigation:
 * - $main_menu (array): An array containing the Main menu links for the
 *   site, if they have been configured.
 * - $secondary_menu (array): An array containing the Secondary menu links for
 *   the site, if they have been configured.
 * - $breadcrumb: The breadcrumb trail for the current page.
 *
 * Page content (in order of occurrence in the default page.tpl.php):
 * - $title_prefix (array): An array containing additional output populated by
 *   modules, intended to be displayed in front of the main title tag that
 *   appears in the template.
 * - $title: The page title, for use in the actual HTML content.
 * - $title_suffix (array): An array containing additional output populated by
 *   modules, intended to be displayed after the main title tag that appears in
 *   the template.
 * - $messages: HTML for status and error messages. Should be displayed
 *   prominently.
 * - $tabs (array): Tabs linking to any sub-pages beneath the current page
 *   (e.g., the view and edit tabs when displaying a node).
 * - $action_links (array): Actions local to the page, such as 'Add menu' on the
 *   menu administration interface.
 * - $feed_icons: A string of all feed icons for the current page.
 * - $node: The node object, if there is an automatically-loaded node
 *   associated with the page, and the node ID is the second argument
 *   in the page's path (e.g. node/12345 and node/12345/revisions, but not
 *   comment/reply/12345).
 *
 * Regions:
 * - $page['help']: Dynamic help text, mostly for admin pages.
 * - $page['highlighted']: Items for the highlighted content region.
 * - $page['content']: The main content of the current page.
 * - $page['sidebar_first']: Items for the first sidebar.
 * - $page['sidebar_second']: Items for the second sidebar.
 * - $page['header']: Items for the header region.
 * - $page['footer']: Items for the footer region.
 *
 * @see template_preprocess()
 * @see template_preprocess_page()
 * @see template_process()
 * @see html.tpl.php
 *
 * @ingroup themeable
 */
?>

  <div id="page-wrapper"><div id="page">

    <div id="header"><div class="section clearfix">

      <?php if ($logo): ?>
        <a href="/%3C?php_print_%24front_page%3B_%3F%3E" title="<?php print t('Home'); ?>" rel="home" id="logo">
          <img src="/%3C?php_print_%24logo%3B_%3F%3E" alt="<?php print t('Home'); ?>" />
        </a>
      <?php endif; ?>

      <?php if ($site_name || $site_slogan): ?>
        <div id="name-and-slogan">
          <?php if ($site_name): ?>
            <?php if ($title): ?>
              <div id="site-name"><strong>
                <a href="/%3C?php_print_%24front_page%3B_%3F%3E" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
              </strong></div>
            <?php else: /* Use h1 when the content title is empty */ ?>
              <h1 id="site-name">
                <a href="/%3C?php_print_%24front_page%3B_%3F%3E" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
              </h1>
            <?php endif; ?>
          <?php endif; ?>

          <?php if ($site_slogan): ?>
            <div id="site-slogan"><?php print $site_slogan; ?></div>
          <?php endif; ?>
        </div> <!-- /#name-and-slogan -->
      <?php endif; ?>

      <?php print render($page['header']); ?>

    </div></div> <!-- /.section, /#header -->

    <?php if ($main_menu || $secondary_menu): ?>
      <div id="navigation"><div class="section">
        <?php print theme('links__system_main_menu', array('links' => $main_menu, 'attributes' => array('id' => 'main-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Main menu'))); ?>
        <?php print theme('links__system_secondary_menu', array('links' => $secondary_menu, 'attributes' => array('id' => 'secondary-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Secondary menu'))); ?>
      </div></div> <!-- /.section, /#navigation -->
    <?php endif; ?>

    <?php if ($breadcrumb): ?>
      <div id="breadcrumb"><?php print $breadcrumb; ?></div>
    <?php endif; ?>

    <?php print $messages; ?>

    <div id="main-wrapper"><div id="main" class="clearfix">

      <div id="content" class="column"><div class="section">
        <?php if ($page['highlighted']): ?><div id="highlighted"><?php print render($page['highlighted']); ?></div><?php endif; ?>
        <a id="main-content"></a>
        <?php print render($title_prefix); ?>
        <?php if ($title): ?><h1 class="title" id="page-title"><?php print $title; ?></h1><?php endif; ?>
        <?php print render($title_suffix); ?>
        <?php if ($tabs): ?><div class="tabs"><?php print render($tabs); ?></div><?php endif; ?>
        <?php print render($page['help']); ?>
        <?php if ($action_links): ?><ul class="action-links"><?php print render($action_links); ?></ul><?php endif; ?>
        <?php print render($page['content']); ?>
        <?php print $feed_icons; ?>
      </div></div> <!-- /.section, /#content -->

      <?php if ($page['sidebar_first']): ?>
        <div id="sidebar-first" class="column sidebar"><div class="section">
          <?php print render($page['sidebar_first']); ?>
        </div></div> <!-- /.section, /#sidebar-first -->
      <?php endif; ?>

      <?php if ($page['sidebar_second']): ?>
        <div id="sidebar-second" class="column sidebar"><div class="section">
          <?php print render($page['sidebar_second']); ?>
        </div></div> <!-- /.section, /#sidebar-second -->
      <?php endif; ?>

    </div></div> <!-- /#main, /#main-wrapper -->

    <div id="footer"><div class="section">
      <?php print render($page['footer']); ?>
    </div></div> <!-- /.section, /#footer -->

  </div></div> <!-- /#page, /#page-wrapper -->
  • style.css: The Cascading Style Sheet for the theme; this is needed only for styling unique to the theme
  • .info: The most important file for any Drupal theme. This file sets a number of parameters for your theme, including the theme's name, description, and version information

Using Bartik as an example a .info file would look like this:

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

Recommended files:

  • template.php
  • maintenance-page.tpl.php
  • node.tpl.php
  • html.tpl.php

Optional files:

  • theme-settings.php
  • block.tpl.php
  • comment.tpl.php

* In theory every module output has a template file. Use the necessary templates files that will get the job done for your site. If you would like to determine what template files are available the Devel module with theme developer is a great asset for this purpose. Make sure you also include the required simplehtmldom to avoid conflict issues.

Customizing Order

If you need to make a small changes consider customizing in this order:
  1. Use CSS to manipulate design 
  2. Use template.php for structural changes
  3. Add new template files to theme
  4. Use a module - for major feature additions

Stark As Your Reference Guide

Though Stark is not intended for use on a site in its raw form, as it's not a true theme due to the lack of a page.tpl.php file, the theme can still be used as a tool. It is included to demonstrate the default HTML markup and CSS styles, and provides a reference point for you to use when creating your own themes or working with the system styling.
 
Features of the Stark theme:
  • Flexible width that adjusts to the user's display
  • Seven regions to choose from
  • Supports one, two, or three-column layout

Sub-themes for quicker development 

Get up and running fast by letting an existing theme do most of the heavy lifting for you. Instead of creating a new theme from a blank canvas, you can create a sub-theme, that is esentially a new theme that uses part of the files, styles, and templates of it's parent theme; until overridden. For many, designing from a base theme is a painless way to create a new theme.

The approach to sub-themes will have you searching for an existing theme that meet part of your needs; then you simply create a sub-theme based on that theme. Once you have created the sub-theme you can modify it to fit your needs. To make this approach even more attractive, there are themes that are specifically intended for use as the starting point for sub-themes.

Using A Theme For Sub Theming

As previously stated; the easiest way to get up and running without the headache of starting from scratch is to use a theme and create a sub-theme from there only overriding the functionality that best suits your website. There are over 1,500 Drupal themes to choose from (at the time of writing) but the following themes are a few that we would recommend.  

Many of these themes serve a different purpose for a specific use-case install and customize the theme that best handles your situation.

Use Your Resets!

If you decide to creating your own theme a nice file to have will consists of a reset.css file. The goal of a reset stylesheet is to reduce browser inconsistencies in things like default line heights, margins and font sizes of headings, and so on. A good example provided below is the reset by Eric Meyer. Eric Meyer's CSS reset does not have any colours which leaves most of the styling up to the designer. The CSS reset stylesheet looks like this:

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
table {
	border-collapse: collapse;
	border-spacing: 0;
}

You can add this to your style.css file or, even better, create a reset.css file and have your .info file load the file.

Conclusion

Despite the apparent complexity one sees at first glance, Drupal themes can be managed in a logical and relatively easy fashion by working with theme files (never hack core) and through applying your own styling to intercept and override the default formatting of the Drupal system or base theme.
 
A good place to start looking for a Drupal theme is the official Drupal site. At Drupal.org, there you will find a variety of ready-to-use themes

Further Reading

Lyemium's Guide To Drupal 7

7 Well Designed Drupal Themes You Can Install Now

Theming Drupal 6 and 7

Standard Drupal core styles and classes

Overriding themable output