I have a themes which inherit from zen template. The zen template has an html.tpl.php, and I would like to override that html.tpl.php for one content type.

Let's say my theme name is test and my content type is called foo, I have tried the following code snippet into my template.php located in my test theme

function test_preprocess_html(&$vars){
  if (!empty($vars['node'])) {
    $vars['theme_hook_suggestions'][] = 'html__node_' . $vars['node']->type;

Then I have created my html template named html--node-foo.tpl.php in the templates folder.

And, it doesn't works! I keep having the default zen html template loaded.

Here is the source of the html.tpl.php file in the zen templates folder

Ps: the following snippet works for overriding the pages templates depending on node type. Why does the above snippet doesn't works?

function test_preprocess_page(&$variables) {
  if (!empty($variables['node'])) {
    $variables['theme_hook_suggestions'][] = 'page__node_' . $variables['node']->type;

2 Answers 2


Jonathan, your missing an underscore...

function test_preprocess_html(&$vars){
  if (!empty($vars['node'])) {
    $vars['theme_hook_suggestions'][] = 'html__node__' . $vars['node']->type;

Your get it if you see whats suggested already be doing a var_dump($vars).

This has nothing to do with the Zen theme, it's just core functionality.

To understand how this is formed you can take a look at the theme_get_suggestions() function in theme.inc

 * Generate an array of suggestions from path arguments.
 * This is typically called for adding to the 'theme_hook_suggestions' or
 * 'classes_array' variables from within preprocess functions, when wanting to
 * base the additional suggestions on the path of the current page.
 * @param $args
 *   An array of path arguments, such as from function arg().
 * @param $base
 *   A string identifying the base 'thing' from which more specific suggestions
 *   are derived. For example, 'page' or 'html'.
 * @param $delimiter
 *   The string used to delimit increasingly specific information. The default
 *   of '__' is appropriate for theme hook suggestions. '-' is appropriate for
 *   extra classes.
 * @return
 *   An array of suggestions, suitable for adding to
 *   $variables['theme_hook_suggestions'] within a preprocess function or to
 *   $variables['classes_array'] if the suggestions represent extra CSS classes.
function theme_get_suggestions($args, $base, $delimiter = '__') {

  // Build a list of suggested theme hooks or body classes in order of
  // specificity. One suggestion is made for every element of the current path,
  // though numeric elements are not carried to subsequent suggestions. For
  // example, for $base='page', http://www.example.com/node/1/edit would result
  // in the following suggestions and body classes:
  // page__node              page-node
  // page__node__%           page-node-%
  // page__node__1           page-node-1
  // page__node__edit        page-node-edit

  $suggestions = array();
  $prefix = $base;
  foreach ($args as $arg) {
    // Remove slashes or null per SA-CORE-2009-003 and change - (hyphen) to _
    // (underscore).
    // When we discover templates in @see drupal_find_theme_templates,
    // hyphens (-) are converted to underscores (_) before the theme hook
    // is registered. We do this because the hyphens used for delimiters
    // in hook suggestions cannot be used in the function names of the
    // associated preprocess functions. Any page templates designed to be used
    // on paths that contain a hyphen are also registered with these hyphens
    // converted to underscores so here we must convert any hyphens in path
    // arguments to underscores here before fetching theme hook suggestions
    // to ensure the templates are appropriately recognized.
    $arg = str_replace(array("/", "\\", "\0", '-'), array('', '', '', '_'), $arg);
    // The percent acts as a wildcard for numeric arguments since
    // asterisks are not valid filename characters on many filesystems.
    if (is_numeric($arg)) {
      $suggestions[] = $prefix . $delimiter . '%';
    $suggestions[] = $prefix . $delimiter . $arg;
    if (!is_numeric($arg)) {
      $prefix .= $delimiter . $arg;
  if (drupal_is_front_page()) {
    // Front templates should be based on root only, not prefixed arguments.
    $suggestions[] = $base . $delimiter . 'front';

  return $suggestions;

Have a look at the $delimter argument. The default is '__' for theme_hook_suggestions().


Maybe you simply have a typo in the code?

You get $vars in the template declaration but you're checking for !empty($variables['node']) (Which will always be false) it should be !empty($vars['node'])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.