I need to add a class name to certain labels created by Drupal's form API like this:

$form['name'] => array(
  '#type' => 'textfield',
  '#title' => 'Prénom'

If I use the following, the <textarea> gets a class, but not the label.

$form['name']['#attributes']['class'] = array('myClass');

I'm looking for something similar that will add a class to the <label>.

  • You should also consider if you can't already target that field label with CSS using the parent container class for the field name, e.g .field-name-field-myfield label{ color:red; } Jan 29 '13 at 22:12

You cannot set a class to the label tag of the form element using Form API's properties. However, you can set a prefix and a suffix to wrap the element (label + textarea) and use some nested CSS selector to accomplish what you are trying to do.

$form['name'] => array(
  '#type' => 'textfield',
  '#title' => 'Prénom'
  '#prefix' => '<div class="myClass">',
  '#suffix' => '</div>'

and in the CSS, you can select the label tag like this:

.myClass label {
  text-transform: uppercase; /* just for example */

Not a decent solution but that's how I usually do this, and have seen others do. #attributes is for the input element itself so it's correct your code adds the myClass class to the textarea.


This post on StackOverflow says that the Drupal Form API does not support adding classes to labels, but it does contain a decent workaround:

Instead, you could target it using the wrapper class for the field and label:

.form-item-field-foo label {
  /* CSS here */

The API documentation for theme_form_element_label() shows why labels aren't possible (at least not out-of-the-box): the attributes array is initialized in the theme function and populated with just two optional classes ('option' and 'element-invisible').

So, is it completely impossible? In fact, I think it can be done, but I must add that I haven't tried this myself. You could try to:

  • Add a new #label_attributes property to some (or all) form elements using hook_element_info_alter() in a custom module;
  • Override theme_form_element_label() and make it merge the $attributes array with the value of $element['#label_attributes'].

If you're going to give this a try, please let us know if it worked.

  • Due to time constraints, I will go for the easier solution proposed by Ayesh K. This looks like a good solution though, it may help somebody else. +1
    – Shawn
    Jan 30 '13 at 15:13
  • Plus 1 for mentioning the theme_form_element_label() theme function
    – Ideogram
    Aug 14 '14 at 7:59
  • Workarounds: if requiring JS on the site is acceptable, tweaking the DOM is probably easiest. If not, another (mean) way would be to remove '#title' or set '#title_display' => 'invisible' and then just do '#suffix' => '<label for="TheElementId" class="option">Display This Text</label>'. That causes it to appear outside of the wrapper <div> Drupal uses for its form-input elements, but a CSS rule could make it look no different. Jun 24 '16 at 5:51

On Drupal 8, do that simply by adding in your_module.module file

function your_module_preprocess_form_element(&$variables) {

  $element = $variables['element'];
  if (isset($element['#label_attributes'])) {
    $variables['label']['#attributes'] = array_merge(

and add the #label_attributes on form creation :

$form['some_field'] = [
  '#label_attributes' => [
    'some_attr' => 'some_value',

Expanding on Ayesh's answer I have included an example use case for such code. While marvangend's answer is much more Drupalesk it's a lot of digging for a very simple result. Keeping form specific elements & CSS bundled with said form is the general use case, allowing us to target & act on inner elements is a tiny bit more specific.


function mymodule_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id) {
    // Waterfall.
    case 'webform_client_form_16':
    case 'webform_client_form_51':
    case 'webform_client_form_64':
    case 'webform_client_form_78':
      $exclude = array('select', 'radios', 'checkboxes', 'managed_file');
      foreach ($form['submitted'] as $name => $component) {
        if (!in_array($component['#type'], $exclude) && $name != '#tree') {
          $form['submitted'][$name]['#prefix'] = '<span class= "label-invisible">';
          $form['submitted'][$name]['#suffix'] = '</span>';
          $form['submitted'][$name]['#attributes']['placeholder'] = $component['#title'];
      $form['#attached']['css'] = array(
        drupal_get_path('module', 'mymodule') . '/css/mymodule.form.css',

I found a relatively easy way to accomplish this using the Fences D7 module. This module comes with a lot of template files to customize the fields. Edit the field that you would like to give a unique class to and change the wrapper markup to something relevant for you. After that, find the corresponding template file within the module and copy it into your sites/all/themes/THEME_NAME.


<span class="field-label"<?php print $title_attributes; ?>>
  <?php print $label; ?>:


<span class="<?php print $label; ?> field-label"<?php print $title_attributes; ?>>
  <?php print $label; ?>:

By adding in <?php print $label; ?> , it prints the name of the field as a class, allowing you to target all of the field-labels individually. I hope this helps someone else!


It's dirty, but you can add HTML to the '#title'-property:

$form['some_element'] = array(
  '#type'          => 'textfield',
  '#title'         => '<span title="HELP!">'.t($subchildlabel).'</span>',
  '#default_value' => …

I'm surprised myself it works. I would think Drupal would filter this out, but no. So, you can wrap the label with another class:

<label for="edit-m-vernacularname" class="inline"><span title="HELP!">Common name
</span> </label>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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