Notable changes to theming in Drupal 7

There are 50+ changes to the theme system in the move to Drupal 7 – that’s a lot to consider when upgrading your theme from Drupal 6 to Drupal 7. As expected, some of the changes make theming more complex… but those changes can also free things up for you to do complex things in a simpler way. Some things have been broken down into smaller pieces so you can do more with them, and some tasks you did repetitively across different themes are now automated.

Node Jenga

So far, you’ve come to grips with two common ways of getting fields to print in the node template (in the order you want):

  1. Drag and drop fields into the order you want them via the “Manage Fields” page for a given content type in that content type’s Manage Fields page.
    This is only a global solution for your site, and you don’t really have a way to sort fields in different contexts. Your node template gives you $content which prints out all the fields associated with that node. While this works just fine for simple sites, what happens when you want the fields to display in different orders when seen in different situations? In Drupal 6, if you want your node to display its fields in a certain order for the “full” node version, but in a different order for its teaser version, then you’re out of luck (without writing custom code or perhaps using a contrib module for that functionality).
  2. Print fields out directly.
    If you want to print out certain fields, you’ve been able to search the $node object for the particular field you want and print it directly, getting around having to use $content altogether. An example of that would be content['field_myfieldname']['#value']; ?>

In Drupal 7, you can sort fields for both the “default” and “teaser” formats, among others, from the content type’s “Manage Display” page. However, be aware that if you rearrange your fields in the manner, it also affects the order of the fields shown on your node’s “edit” form (a tip of the hat to commenter Matthias for making this point). If you want to order your fields in a way that the “Manage Display” page won’t allow you to… or if you don’t want your node edit form mangled, you can take your node’s $content and print things however you want (or conversely, NOT print things) from within the template, so you never have to mess with the content’s “Manage Display” page, or break apart $node. For this approach, we have two new functions available to us:

  • hide()
    Now you can use, for example, at any point before the content gets printed and those parts of the $content will not be rendered with everything else.
  • render()
    So you’ve decided which fields/parts of $content you don’t want in the big old chunk of $content, and now you use to print the rest. Everything that wasn’t first hidden with hide() will now be printed out. You can then use to print what you originally hid in $content.

Of course, if you can sort your fields the way you want them using the admin pages for your content type, you should probably do that before adding unnecessary code to your node templates or preprocess functions.

Say goodbye to .clear-block

The Drupally way of clearing floats within container elements was the .clear-block class. In Drupal 7, this class has been renamed to .clearfix. This seems to be a little more descriptive of the point of the fix in the first place, and does less to confuse beginners with Drupal’s “block” system which is unrelated.

Hiding stuff

Special standard classes to identify elements as hidden have been added to core CSS:

.element-hidden is for hiding things on page load, and it can be used in junction with jQuery’s .show() and .hide() to toggle something as hidden or not. An example of usage of this class attribute would be to put it on a dropdown menu (

or

    , or whatever floats your boat) that only displays when its parent main menu item has been hovered on.

    .element-invisible is for elements you want permanently hidden (but still viewed on screen readers for accessibility reasons). If you ever do any image/text replacement work, you can probably see how this will be useful.

    Form overrides

    When I first got started with Drupal, I found it particularly difficult as a themer with beginner’s PHP skills trying to figure out how to take a form and make modifications: re-order fields, change labels, remove fields, add markup… that kind of thing. Eventually you learn that form overrides can be done in a custom module using hook_form_alter(), or by using hook_theme() in template.php to establish a form override function and do your magic there. As a themer, in most cases, your form changes don’t fundamentally change how the form’s functionality works, and you usually do your form override in template.php.

    Well, now hook_form_alter() is available for use in the theme layer. This means you don’t have to go through hook_theme() anymore and you can just jump in and modify whatever for you want using the $form_id that comes in as an argument via hook_form_alter() and hook_form_FORM_ID_alter():

    For example, to add a new “search-field” class to your search block’s text field, you would simply drop the following into your theme’s template.php:


    function yourtheme_form_alter(&$form, &$form_state, $form_id) {
    if ($form_id == 'search_block_form') {
    $form['search_block_form']['#attributes']['class'][] = 'search-field';
    }
    }

    As you can see, we’re checking for $form_id to do these overrides on a case-by-case basis. You can add more IF statements to this function to other overrides for different forms. Alternatively, you can use hook_form_FORM_ID_alter() to break your forms into separate functions, like this:


    function yourtheme_form_search_block_form_alter(&$form, &$form_state, $form_id) {
    $form['search_block_form']['#attributes']['class'][] = 'search-field';
    }

    So, form overrides are a little bit easier and simpler in Drupal 7.

    In related news, fellow Advomatic developer Aaron Winborn discovered today that ALL _alter functions are now available to the theme layer in D7 (currently happening in the middle of drupal_alter() if you’re curious). This allows for things like hook_js_alter() or hook_css_alter() in themes, which some of you may find useful.

    Thanks for reading, and stay tuned for part two.