2

I have a form with id equal to webform_client_form_3. I have a particular field that I'm altering by applying a class to it like so:

$form['submitted']['estimated_annual_distribution_of_effort']['sensor_technology']['#attributes']['class'][] = 'span1';

This all works great. However, I also need to add a class on to the label for that particular element as well. Looking through the $form array, I haven't been able to find anything that gives access to the labels. Am I just missing something or are the labels not part of the $form array?

1 Answer 1

1

The attributes for labels are hard-coded into the theme_form_element_label() function. You can override it at the theme/module level but you'll have to do so for all labels in the system as the variables passed to the theme function do not contain the form context.

The easiest thing to do would be to add a predictable class to each label in every form (based on the name of the form element that the label is for), and then use a CSS selector based on a combination of your form ID and the label class to target it.

Unfortunately there's a fair bit of code you'll need to copy over, and only one small change you'll need to make, but I can't think of another way to do it:

function MYTHEME_form_element_label($variables) {
  $element = $variables['element'];
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  // If title and required marker are both empty, output no label.
  if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) {
    return '';
  }

  // If the element is required, a required marker is appended to the label.
  $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : '';

  $title = filter_xss_admin($element['#title']);

  $attributes = array();
  // Style the label as class option to display inline with the element.
  if ($element['#title_display'] == 'after') {
    $attributes['class'] = 'option';
  }
  // Show label only to screen readers to avoid disruption in visual flows.
  elseif ($element['#title_display'] == 'invisible') {
    $attributes['class'] = 'element-invisible';
  }

  if (!empty($element['#id'])) {
    $attributes['for'] = $element['#id'];
  }

  // NEW CODE HERE
  $label_class = 'label-for-' . $element['#id'];
  $attributes['class'] = isset($attributes['class']) ? $attributes['class'] . ' ' . $label_class : $label_class;

  // The leading whitespace helps visually separate fields from inline labels.
  return ' <label' . drupal_attributes($attributes) . '>' . $t('!title !required', array('!title' => $title, '!required' => $required)) . "</label>\n";
}

Once you put that code in your theme's template.php file and clear the cache, you'll be able to target the label with CSS like so:

form#webform_client_form_3 label.label-for-edit-field-name
2
  • Hi Clive. Thanks for pointing out theme_form_element_label. I'm still getting used to the Drupal API docs... they're not exactly intuitively laid out. I came up with an alternate approach to your solution that lets me target specific labels and add existing CSS classes rather than creating new CSS classes and duplicating rule definitions. I'm creating a blog post about it, and will post a link here afterwards. Commented Apr 24, 2012 at 17:48
  • Link to my blog post about my tweak to your code lespeabody.net/blog/…. I'd be curious to hear your thoughts on my approach. Commented Apr 24, 2012 at 20:02

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.