10 Tips for Theming Drupal 6 Forms

In the last month, I’ve been working on a project that requires a very custom look and feel for login/register/adding content forms, and worked what I’ve learned into a presentation. Now I’ve got a little running list of tips for whipping Drupal forms into shape.

  1. Check out the Stealther plugin. If you are theming a form that logged in users don’t see (like the Login or Registration forms) Firefox’s Stealther plugin is invaluable. Since it temporarily disables saved information – caches, cookies, histories, form information – you can quickly toggle back and forth to see what the logged out user sees.
  2. Let anonymous users see Devel information. You can extend the Stealther idea even further using the Devel module. Install and expose the Devel menu. If you are on a private development site, give anonymous users full permissions on the Devel module. This will allow you do use the devel tools (theme developer, clear cache, run cron, $dpm(); etc.) without being logged into the site, so you can easily inspect and theme forms for anonymous users. Be SURE to disable these permissions once done using them.
  3. Keep your CSS organized.If you are doing a LOT of CSS theming of your forms throughout your site, consider making a separate forms.css file. That can help you keep your styles organized. Just make sure you add the call to that stylesheet (stylesheets[all][] = forms.css) in your .info file and clear you cache to get Drupal to recognize it.
  4. Theme “active” fields.For usability, highlight the field the user’s cursor is in. Using a CSS3 class, change the current field’s background color or border:

    input:focus {
    background-color: orange;
    border: 1px solid black;
  5. Substitute jQuery for CSS3 tricks for usability. Override tip #4 with this additional twist. IE does not support many CSS3 pseudo-classes (including IE8), so use jQuery for focus/hover/after effects instead of CSS3 for cross-browser compatibility. Use jquery to add a class to your input upon “focus”, then style that class in your stylesheet:

    $("input").focus(function() {


    input.focus {
    background-color: orange;
    border: 1px solid black;

    You can apply this class to the input wrapper instead with $(this).parent().addClass("focus");

    Also, use this method to add classes when hovering over elements.

  6. Theme fields that produce errors. Drupal adds an error class to input fields that produce an error when submitted. Use that class to guide users to where their problem is with a form by outlining it or other styling. Also check out this tutorial for applying the error class to the field wrappers so you can also theme the field labels or the entire form element area producing the error.
  7. Use dpm($form);. If you are using a function to override parts of your form in your template.php file (and you have the Devel module installed), you can use dpm($form); in your function to check your variables and figure out what is overrideable content. It prints out your variables in a nice, expandable stack.
  8. Check for different permissions or variables before loading or unsetting form elements. Inside your function, you can also check for various states. For example, if you are overriding a node creation form, you can check to see if you are on the Preview page or not with:

    Or check to see what kinds of permissions the user filling out the form has:

  9. Consider using a form tpl.php file. Once you have created your function to override your template, you can easily add a tpl.php template file, which is often easier for themers more comfortable with the XHTML structure than the PHP. However, because TPL files render about five times slower than functions, try to do as much as you can with a function. If it starts getting hairy and your function is super long, maybe then it should be moved to a tpl.php file.
  10. …But be sure to load your hidden form elements! If you go with the method in #9 and add a your-form.tpl.php file, make sure to render the hidden form elements. If not, your form will not submit! I keep this bit at the end of my tpl.php file, just to be on the safe side:

    Update: A reader below has pointed out that this method, while it works now, relies on things in the Form API that could potentially change in the future. To avoid this problem, use instead. In this scenario, however, you will need to unset any fields that you do not want to show because will print everything that hasn’t rendered already on your form.


And please add your favorite tricks in the comments!