Last updated August 8, 2013. Created by Todd Nienkerk on December 2, 2008.
Edited by oadaeh, eojthebrave, Carolyn, ldpm. Log in to edit this page.

Depending on how your site is configured, the HTML code that makes up each page in your site is compiled from the output of various Drupal modules.

About modifying HTML markup

If the default HTML markup supplied by any module does not suit the requirements of your theme, you can override some or all of it, so that the resulting page is exactly what you need for your design.

For example, you might decide that for your site, the default search box should have an image of a magnifying glass and that the label on the search button should read "Discover great stuff!" rather than the default label of "Search". You can completely override the default markup, so that the markup calls for your image file and that the button is labeled the way you want.

Don't hack core

It's very important to understand the concept of "overriding". While it is technically possible to just find the module responsible for the search field and edit the code directly, this is definitely NOT recommended. In the short term, it will seem to solve your problem, but it will soon make it difficult to keep your site up to date. Whenever you update the module, perhaps for a general security release, you would need to remember to redo any of your customizations.

How to change HTML the Drupal way

The "Drupal Way" is to do an override. This involves four basic steps:

  1. Locate the module responsible for the markup
  2. Do one of the following:
    • If the module provides a template (tpl.php file), copy the template to your theme directory. See Core Templates and Suggestions for a list of core templates. OR...
    • In the module code, identify the theme or preprocess function that is generating the markup you want to change and copy the function to your theme's template.php file. You will need to change the "theme_" or "template_" prefix to match the name of your theme. For example, "theme_breadcrumb" would become "mythemename_breadcrumb"; "template_preprocess_page" would become "mythemename_preprocess_page".
  3. Within the copied function or template, change the HTML code to suit your needs.
  4. Refresh the theme cache.

The About overriding themeable output page provides a more in-depth look at overriding Drupal's default markup and the underlying system that makes it possible.

These steps are explained in greater detail in the following pages.

Using PHP for theming

If you are not already familiar with PHP, the process might seem somewhat intimidating, but it generally does not require that you understand anything about actually writing PHP. As long as you know what HTML you want to be displayed, it's simply a matter of modifying that part of the code. As with any theming work, you should not make changes to a live or production site until you have thoroughly tested the changes on a development site.

Overriding CSS

Many modules also provide style sheets (.css files) which specify the default look and feel of the markup. These style sheets can also be overridden. For more information, see Overriding style sheets from modules and base themes.

Popular Contributed Modules that override the default HTML output

Some contributed modules have their own theming guides. Also see overriding style sheets from modules and base themes.

Modules for which theming-specific documentation exists are listed below by Drupal version.

Drupal 7–compatible modules

Drupal 6-compatible modules

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

If the default HTML markup supplied by any module does not suit the requirements of your theme, you can override some or all of it, so that the resulting page is exactly what you need for your design.

Although largely true, I am finding this not to be entirely true.

  • The "Link this field to its node" in the Views 2 module cannot be overrode, in this way, to produce absolute URLs.
  • There is no core solution for Theming more than one taxonomy vocabulary. There is also no core solution for theming taxonomy term hierarchies.

There is no core solution for Theming more than one taxonomy vocabulary. There is also no core solution for theming taxonomy term hierarchies.

Yes there is: see http://drupal.org/project/tvi

TVI is in Beta but it is stable.

- Derek

"Overriding themable output"...? As a newbie that title makes no sense. Perhaps that title could be clarified to be in newbie-understandable language?

Simon.

[Edited Later]
OK, newbies might find this basic tutorial a great read to get started:
http://drupalsn.com/learn-drupal/drupal-tutorials/drupal-theme-function-...

function phptemplate_hook($... is for Drupal 5 and in Drupal 6 replaced with themename_preprocess_hook(&$var...

the question is how exactly? a simple example function to override a submit button on an views exposed filter would be really really helpful. anyone, please?

function mythemenamec_preprocess_views_exposed_form(&$variables) {
....
}

please can someone fill in the dots to simply change the submit button text to 'Go' instead of the default 'Apply'

thanks

I used this for my site:

<?php
function searchblocklayout_form_alter(&$form, $form_state, $form_id) {
//this snippit shows me my arrays before i start theming
//after you copy and paste it somwhere else, comment it out again
//echo "<pre>";
//print_r($form);
//echo "</pre>";
if($form['#id'] == 'views-exposed-form-job-search-block-1') {
$form['keys']['#size'] = '44';
$form['keys']['#id'] = 'views_search';
$form['keys']['#value'] = 'Enter keywords (i.e., driver, nurse, etc.)';
$form['tid']['#id'] = 'views_dropdown';
$form['tid']['#options']['All'] = 'All job categories';
$form['submit']['#value'] = 'Search';
}
}

First off this is to edit a Views template in a totally different method, but the PHP is still the same inside the function.

As you can see, to my search box with the name 'keys', I changed the width, assigned it an ID and gave it an initial value. For my dropdown filter based on a vocabulary, I gave it an ID and initial value as well. I also renamed the search button.

(Also a hint: those strings starting with '#' are HTML attributes)

Granted there are a few more things you would want to do, such as throw a snippit of Javascript in to remove the text (using onClick or onFocus) but hopefully you can print the array out and clear up the confusion!