General Steps for Custom Theming Drupal 7

By t.wheeler on Jul 9, 2012 - 09:10am

A lot of students get stuck trying to figure out even just how to start with creating a custom theme for Drupal.  Totally understandable.. I started with Drupal many years ago but I remember being stuck a lot!  So here's my tips for you to get you started, based on my own experience with building tons of Drupal sites.. Hope this helps you!

There are many Drupal themes you can look at for reference. In my opinion, the fastest and easiest way to start if you have a good understanding of CSS, and a basic understanding of PHP, is to just start from the core system theme files.  The following are very general tips, and I realize they need to be expanded and explained more.. I'll try to work on that as I get a chance.

Initial Custom Drupal theme set-up:

  1. Install Drupal (obviously).  Basically you just need to copy all the core drupal files to your server, and then run the install.php script there.
    You'll need to create a new database and database user on your server. 
  2. There may be some favorite modules that you'll want to go ahead and install before you even start theming.  Having at least the admin_menu module installed helps me get around much faster to the various config screens and tools within Drupal.  I almost always install the following modules into every Drupal 7 site build:
  3. Create a custom theme folder at /sites/all/themes/[your-theme]   Single word names for themes work best, like "mytheme" or whatever. No spaces in the theme directory (which is also your theme name).  Keep in mind that you will use that theme name in various ways, including probably in names of custom functions you might later write.  So keep it simple.
  4. Make a screenshot from the design file (294px wide). Put it in your theme folder.  Call it "screenshot.png".
  5. Make a logo image, (logo.png) and drop it in there as well.
  6. Make directories there to hold CSS, JS, images and templates.
  7. Make the file – I typically copy a previous project, here's a good example theme .info file: This is where you specify your theme name, the theme's regions, CSS files, and register any javascript files you will be using
  8. Add a general template.php file for preprocess functions and other custom PHP functions you might want to create.  Preprocess functions are quite powerful, and allow you to customize theme variables, and even Drupal's template naming system before the theme initializes. It's a little advanced, so for now just create an empty template.php file at the root of your theme:  /sites/all/themes/[your_theme]/template.php  (same location as the logo, .info, and screenshot).


  1. Copy page.tpl.php from modules/system into your custom theme folder.  This is how the templates work - you can copy any theme template file (ending with .tpl.php) from the module folders into your theme folder.  Templates in the theme layer will override any in the module layer.  You would put them into /sites/all/themes/[your_theme]/templates/.
  2. Edit the new page.tpl.php file in your theme - remove whatever you don't want and make sure that the regions it's attempting to print match the regions you specified in your theme's .info file.  For example, in the default page.tpl.php file you'll see this line that attempts to print the header region:
    print render($page['header']); 
    But if you didn't specify a header region in your .info file, this will throw an error.  Either remove the command in page, or add the header region to the .info file.  Remember that regions are where blocks appear.  You can place multiple blocks into a single region.  And, you MUST have a "content" region.
  3. I often remove the breadcrumbs, and usually the whole header section that attempts to print the site slogan, etc..  - Make sure you don't over-remove things.  If you don't understand what something does, it might be tempting to remove it -- but I've found that these things usually are quite helpful.  Leave them there until you understand what they are doing.   
  4. You might also need other template files, like html.tpl.php, node.tpl.php (from node module), block.tpl.php.  Generally I don’t grab them until I really need them because there's no point to storing them in the theme folder if they aren't used.

Now it's time to activate your Custom theme

  1. Go to Admin > Appearance  - and enable the custom theme.  I usually also disable Bartik, and leave Seven enabled for the admin theme (which will appear in the overlay).
  2. Default Drupal is going to use XHTML, but if you install the html5_tools module the theme will be set up for HTML 5.
  3. Now you're ready to begin styling the site with CSS.  I use Firefox and firebug to identify the markup that Drupal generates and style it.  Go as far as you can with the theme markup using CSS & firebug.  Drupal will give plenty of markup, so you shouldn't need to add much - of course sometimes you will need to, but take a look at what is already there and see if you can just make use of that (it's faster).  Also, don't fuss with trying to rename HTML Id's and Classes that Drupal generates.. that's typically just a waste of time. I just style blocks, menus, nodes and other elements using the generated ID and class names, it's much faster.
  4. Create custom theme template files for node types, blocks, etc..If you’re using a 3rd party module, and it’s generating some output you want to modify, see if there are any theme files (whatever.tpl.php) in the module.
  5. Use custom PHP code – in the theme layer. Any custom functions can be placed into the template.php file.
  6. Sometimes the easiest way to get what you need in your theme is to write a small custom module.

Customize the Homepage

What I usually do for the homepage is to create a custom theme template.  Copy page.tpl.php and name it page--front.tpl.php.  You place this into your theme's template directory.  Now here's a tip that I think is useful:  Drupal by default wants to load teasers of all the latest content into it's main content region on the homepage.  That's not typically what my designs call for...  so I don't print the main content region on the homepage.  I usually make special homepage regions, that are different from the typical content and even sidebar regions of the rest of the site.  

Here's a typical regions list from one of my recent theme's .info files:

regions[header] = Header
regions[page_top] = Page top
regions[page_bottom] = Page bottom
regions[content] = Content
regions[home_content_1] = Home content first
regions[home_content_2] = Home content second
regions[home_content_3] = Home content third
regions[sidebar_first] = Sidebar first
regions[sidebar_second] = Sidebar second
regions[dashboard_sidebar] = Dashboard sidebar
regions[footer] = Footer

Then in my page--front.tpl.php file, I remove the line that attempts to print the main content:

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

and replace that with the name of my homepage content region, (or regions).  Like so:

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

Clear the cache and you're ready to roll. Obviously some homepages are so totally customized, there's not much left from the original page.tpl.php file once I get done with it.  I often strip out a lot of the markup, h1 title, tabs, etc..

You can now create custom blocks, and drop them into these custom homepage regions, and then style away with CSS.  Sometimes I create a node to use for the homepage (it still will be handled through page--front.tpl.php), but other times the homepage is simply a collection of blocks in regions, and there is no node.  

A node is handy though, because often people want a homepage slideshow, which I usually set up with image content fields and then some jquery.

Customizing the Navigation

In the default page.tpl.php file you'll find these lines of code for the navigation:

 <?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; ?>

These work well, and generate a markup that gives you a unique numeric-based class name for each individual link.  Also, by default Drupal helpfully includes the user account / log out links in that secondary menu.  You can of course move these print statements around. Typically you'll want to separate them and move the secondary links into it's own container div.

Another option - and actually one that I use more frequently, is to delete this section entirely and just use the menu blocks.  All available menus will be listed as blocks in the Drupal system.  You can just move the menu blocks up to any region you like (header for example).  It keeps for a cleaner page template file. The only thing you lose is the unique numeric class names on the links.  But I haven't found a big need for those in most of my projects.  Both ways give you classes to indicate which link(s) are "active", and even which link path is the active path.  In other words, if you have nested navigation links to many levels, Drupal will add "active" class to each level of <li> tag, as you click down the link path.   This is great because you can of course assign special styles to the active links.

One of my favorite 3rd party modules I should mention is called "menu_block" - this is great for situations where you want a primary navigation in one place, and a secondary navigation in another location (like the sidebar), but you need them to be all part of the SAME menu. 

Additonal Resources

Also check out my WebVisions Presentation: Crash Course Theming Drupal
For more information go through resources and training with Drupal’s theming guide: