11

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>.

1
  • 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, 2013 at 22:12

7 Answers 7

6

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.

6

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.

3
  • 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, 2013 at 15:13
  • Plus 1 for mentioning the theme_form_element_label() theme function
    – Ideogram
    Aug 14, 2014 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, 2016 at 5:51
5

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(
      $variables['attributes'],
      $element['#label_attributes']
    );
  }
}

and add the #label_attributes on form creation :

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

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.

http://legomenon.io/article/drupal-7-adding-form-placeholder-attributes

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',
      );
    break;
  }
}
0

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.

Before

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

After

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

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!

0

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>
0

I think the easiest way to do tis is to write a bit of jQuery that finds the label for the field and uses the addClass method to add the class.

Drupal puts a unique class in the the div wrapper for each field. Inspect your source to find the class, and you can then jQuery for the child label.

For example in Drupal 7

Create a js file for your theme.

Add in this

(function ($) {
Drupal.behaviors.addLabelclass = {
    attach: function (context, settings) {
        $(document).ready( function () {
            $("div.uniquefieldclass label").addClass("mylabelclass");
            }
            );
        }
};
}(jQuery));

Substitute uniquefieldclass for your class. This jQuery will add the class mylabelclass to the label

1
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Jun 21, 2023 at 16:23

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.