Labels should not have "for" attribute for non labelable elements

Created on 3 June 2014, about 10 years ago
Updated 27 August 2023, 10 months ago

According to the HTML specification when using the "label" element the "for" attribute should only be used when the element you're labelling is "labelable". See: http://www.w3.org/html/wg/drafts/html/master/forms.html#the-label-element

Labelable elements are:
button
input (if the type attribute is not in the Hidden state)
keygen
meter
output
progress
select
textarea

Currently the theme_form_element_label($variables) function takes no account of the type of the element it is labelling. As long as there's an ID for the element it adds this as the "for" attribute. This is done where it does this:

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

The "for" attribute is not a required attribute so presumably we could just add an array of element names or Drupal form element types in this function to exclude the "for" attribute?

The reason this has come up is that a site we manage failed an accessibility check run by the Shaw Trust in the UK. The issue they raised was that there are labels without a corresponding element. In fact, they do have an element, it's just that it's a div. The specific example is a form created using the entityform module which includes a list of checkboxes. Now although that's a contrib module it uses the standard Drupal core field rendering code. An example of the resultant code for checkboxes is something like:

<div class="form-item form-type-checkboxes form-item-field-a3-posters-location-und">
  <label for="edit-field-a3-posters-location-und">Location </label>
 <div id="edit-field-a3-posters-location-und" class="form-checkboxes"><div class="form-item form-type-checkbox form-item-field-a3-posters-location-und-Adam-and-Eve-Street-car-park">
 <input id="edit-field-a3-posters-location-und-adam-and-eve-street-car-park" name="field_a3_posters_location[und][Adam and Eve Street car park]" value="Adam and Eve Street car park" class="form-checkbox" type="checkbox">  <label class="option" for="edit-field-a3-posters-location-und-adam-and-eve-street-car-park">Adam and Eve Street car park (2 sides; behind Grafton centre) </label>

</div>

The only problem with that code is that the label's "for" attribute refers to the id of a div which is not a "labelable" element.

We have got round this for the very specific instance of checkboxes by implementing theme_form_element_label($variables) in our theme but this is a very specific override and not appropriate to core. Our full override function is as follows (it will be extended to pick up other element types in future):

function theme_form_element_label($variables) {
  // run the regular theme function on it
  $output = theme_form_element_label($variables);
  
  // check if it's checkboxes
  if ($variables['element']['#type'] == 'checkboxes') {
    // if it is, strip out the "for" attribute
    $output = preg_replace('#\s(for)="[^"]+"#', '', $output);
  }
  return $output;
}
🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Form 

Last updated about 2 hours ago

Created by

🇬🇧United Kingdom specky_rum

Live updates comments and jobs are added and updated live.
  • Accessibility

    It affects the ability of people with disabilities or special needs (such as blindness or color-blindness) to use Drupal.

  • Needs backport to D7

    After being applied to the 8.x branch, it should be considered for backport to the 7.x branch. Note: This tag should generally remain even after the backport has been written, approved, and committed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇦🇺Australia klonos 90% Melbourne, Australia - 10% Larissa, Greece

    @katannshaw and @Amber Himes Matz admittedly this is a hard problem to fix, but at the same time I don't think that it can be marked as "works as designed".

    To sum up the problem:

    So this for example, is NOT proper use of the label and for attribute:

    <div id="edit-my-item" >
      <label for="edit-my-item">Test item </label>
      <div class="description">Test item description.</div>
    </div>

    After some quick research, the best suggestion I have found is to use a combination of a <span> and the aria-describedby attribute. Something like this for instance:

    <div aria-describedby="label-for-div" >
      <span id="label-for-div">Test item </span>
      <div class="description">Test item description.</div>
    </div>

    Noting the following from https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attribut... :

    1. the aria-labelledby attribute is not appropriate, because it should only be used for interactive elements (which div s are NOT)
    2. the aria-describedby is not ideal either, since it should be used for a description (longer text) rather than a label (short text)

    The purpose of aria-labelledby is the same as that of aria-label . It provides the user with a recognizable, accessible name for an interactive element.

    The aria-labelledby and aria-describedby attributes both reference other elements to calculate text alternatives. aria-labelledby should reference brief text that provides the element with an accessible name. aria-describedby is used to reference longer content that provides a description.

    Reopening this issue in order to figure out a proper solution to this, rather than haste to dismiss it.

  • Status changed to Needs review 10 months ago
  • last update 10 months ago
    30,044 pass
  • 🇫🇮Finland lauriii Finland

    This isn't implementing exactly what is in #17 which I think would be ideal. However, based on #3, it might be an improvement to remove the for attribute when the label is not used for phrasing content. Here's a patch that tries to add support for that in Form API, and adds a use of this to \Drupal\Core\Render\Element\Item.

  • Status changed to Needs work 10 months ago
  • 🇺🇸United States smustgrave

    Should a follow up be made for the other points from #17. Think since this adds improvement it should still move forward. Could the issue summary be updated and tests added?

Production build 0.69.0 2024