5

Can I user form_alter to move move "description" below the "label" for a field in a form?

Let´s say I want to move the "description" of the "body" field for the basic page content type.

7 Answers 7

6

Have a look at Label help module. It just creates a second help field that will appear directly below the form element's label.

It is a simple way to turn around the problem.

Or try something like

jQuery(document).ready(function ($) {

  // move the help text from below the input field to directly below the field label

  $('.form-item .description').each(function () {  // description is the help text
    var desc = $(this);
    var label = desc.siblings('label:first');
     if (label.length) {
       desc.insertAfter(label);
     }
  })
  // the help text is tangled up in the text format stuff on a filtered text field
  $('.text-format-wrapper .description').each(function () {
    var desc = $(this);
    var label = desc.siblings('.form-item').find('label:first');
     if (label.length) {
        desc.insertAfter(label);
     }
  })
});

(thanks to El bandito !)

1
4

Drupal 7

The module Form element layout solves this both at API level and through the Field settings UI.

As a developer you would use the FAPI attribute #description_display and set it before if you want it between the #title and #children, i.e. after the label and before the input element(s):

$form['example'] = array(
  '#type' => 'textfield',
  '#title' => t("Example input"),
  '#description' => t("Example description of what this element does."),
  '#description_display' => 'before',
);

And as a site builder you would just configure your field settings and toggle the description position.

Note: This module will use replacement themes for various parts of Drupal that renders #title and #description, so if your theme already has overridden some of these, they won't "take" anymore and you will have to override the themes provided by Form element layout instead.

Drupal 8

At API level this is already possible using the same FAPI attribute as above, #description_display. In addition to the values before and after it also supports invisible, just like #title_display.

Field UI wise, we're still waiting for issue #2318757.

2

You can't move it, but you can always work around things in Drupal.

A hook_form_alter() or better hook_form_FORM_ID_alter() (for a specific form) would be needed to solve your problem.

Inside the form alter, you can use the following code to place the description in different positions. The example is just for the body field, but you can apply the same logic to other fields as well.

// Get the language of the field
$lang = $form['body']['#language'];
// Check if a description exists
if (!empty($form['body'][$lang][0]['#description'])) {
  $body_field = &$form['body'][$lang][0];

  // Create new description markup and delete the default description
  $description = '<div class="custom-description">'. $body_field['#description'] .'</div>';
  $body_field['#description'] = '';

  // Place description before the field (between label and field)
  $body_field['#field_prefix'] = empty($body_field['#field_prefix']) 
                                 ? $description 
                                 : $description . $body_field['#field_prefix'];
}

And of course, you'll need to add the proper CSS for the new description markup.

0
1

Welcome to the debate. it has been going on for some time.

Check out this discussion for D8: Make position of #description configurable and this: Form Field Description should be between Label and Field. This will give you a perspective on the 5 years I have been watching this. The former has patches to address this, but that means hacking core, unless you wish to create a contributed module. There also seem to be options for moving the description using template.php.

I will leave it to you to join these discussions, and make a decision.

1
  • I see there are a lot of words in this subject. I'll take a look at it. Thanks.
    – chefnelone
    Commented Apr 3, 2013 at 7:40
1

This can be done with hook_form_alter() and #field_prefix. For example, we can take the description of the body field for the basic page content type, and move it directly below the label:

/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, &$form_state, &$form_id) {
  if ($form_id == 'page_node_form') {
    // Move the body's description below the label.
    $language = $form['body']['#language'];
    $form['body'][$language][0]['#field_prefix'] = $form['body'][$language][0]['#description'];
    $form['body'][$language][0]['#description'] = '';
  }
}
2
  • I copied this code into a custom module and it does not work very good unless I remove the line $language = $form['body']['#language']; and remove this in de form structure. Is there a general way to do this for all fields?
    – Justme
    Commented Oct 13, 2016 at 13:05
  • I'd recommend using dpm() or xDebug to inspect the $form object, that way you can identify when/where/if there is a default language for the entire form. Although considered bad practice, if you know your language code is always und, then you can use that in place of $language. Commented Oct 14, 2016 at 2:07
0

Here's a generic way using jQuery

'.form-group p.help-block' 

is the child element is the text you want to move.

'.form-group label' 

is the parent element - this where you want to put the text.

This will move each child element within it's own parent element.

Works for any elements you want to move.

$('.form-group p.help-block').each(function() {
    $(this).insertAfter($(this).parent().find('.form-group label'));
0

This isn't a very Drupally solution, but it was an easy front-end fix. Styles were designed to work with the Olivero 9.5.2 theme. It uses jQuery to move the elements around in the DOM after the page has been loaded (for text fields and fieldgroups so far)

This moves the descriptions up under the labels:

$=jQuery; // lazy hack to keep from typing 'jQuery' repeatedly

// Move the field descriptions just below the label
$(".form-item .form-item__description").each(function(){
  $(this).insertAfter($(this).closest('.form-item').find(".form-item__label:first"));
});

// Move fieldset descriptions to the top of the fieldset contents
$('.fieldset').each(function(){
   $(this).find('.fieldset__description').prependTo($(this).find('.fieldset__wrapper'));
});

Style to taste. I moved the help text and field labels together to flow better with this CSS: /* Fieldgroup label */ .fieldset__description { background-color: #ddd; }

/* Fieldgroup Help Text */
.fieldset__description {
    /* margin-top: 0.5625rem; */
    margin-bottom: 0.5625rem;
    font-size: 0.8125rem;
    /* line-height: 1.125rem; */
    padding: 0.1rem 1.25rem;
    margin: -1.1rem -1.1rem auto -1.1rem;
    border-radius: 0 0 0.5rem 0.5rem;
}

/* Form Field Labels */
.form-item__label {
    background-color: #5d7585;
    color: #fff;
    padding: 0 10px;
}

/* Form Field Help Text */
.form-item__description {
    max-width: none;
    background-color: #eee;
    padding: 0.5rem;
    border-radius: 0 0 1rem 1rem;
    margin-top: -0.55rem;
}

This ends up giving a display like this:

Screenshot of form with fieldgroup help text and field help text moved below labels

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.